The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System, Second Edition

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ipkdb/ipkdb_ipkdb.c

Version: -  FREEBSD  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  cheribsd  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD8-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ipkdb_ipkdb.c,v 1.12 2002/10/11 00:50:31 thorpej Exp $ */
    2 
    3 /*
    4  * Copyright (C) 1993-2000 Wolfgang Solfrank.
    5  * Copyright (C) 1993-2000 TooLs GmbH.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by TooLs GmbH.
   19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: ipkdb_ipkdb.c,v 1.12 2002/10/11 00:50:31 thorpej Exp $");
   36 
   37 #include "opt_ipkdb.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/socket.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/reboot.h>
   43 #include <sys/systm.h>
   44 
   45 #include <net/if.h>
   46 #include <net/if_arp.h>
   47 #include <net/if_ether.h>
   48 
   49 #include <netinet/in.h>
   50 #include <netinet/in_systm.h>
   51 #include <netinet/if_inarp.h>
   52 #include <netinet/in.h>
   53 #include <netinet/ip.h>
   54 #include <netinet/ip_var.h>
   55 #include <netinet/udp.h>
   56 
   57 #include <machine/cpu.h>
   58 #include <machine/reg.h>
   59 
   60 #include <ipkdb/ipkdb.h>
   61 #include <machine/ipkdb.h>
   62 
   63 int ipkdbpanic = 0;
   64 
   65 #ifndef IPKDBKEY
   66 #error You must specify the IPKDBKEY option to use IPKDB.
   67 #else
   68 static char *ipkdbkey = IPKDBKEY;
   69 #endif
   70 
   71 static struct ipkdb_if ipkdb_if;
   72 
   73 static u_char *ipkdbaddr __P((u_char *, int *, void **));
   74 static void peekmem __P((struct ipkdb_if *, u_char *, void *, long));
   75 static void pokemem __P((struct ipkdb_if *, u_char *, void *, long));
   76 static u_int32_t getnl __P((void *));
   77 static u_int getns __P((void *));
   78 static void setnl __P((void *, u_int32_t));
   79 static void setns __P((void *, int));
   80 static u_short cksum __P((u_short, void *, int));
   81 static int assemble __P((struct ipkdb_if *, void *));
   82 static char *inpkt __P((struct ipkdb_if *, char *, int));
   83 static void outpkt __P((struct ipkdb_if *, char *, int, int, int));
   84 static void init __P((struct ipkdb_if *));
   85 static void *chksum __P((void *, int));
   86 static void getpkt __P((struct ipkdb_if *, char *, int *));
   87 static void putpkt __P((struct ipkdb_if *, char *, int));
   88 static int check_ipkdb __P((struct ipkdb_if *, struct in_addr *, char *, int));
   89 static int connectipkdb __P((struct ipkdb_if *, char *, int));
   90 static int hmac_init __P((void));
   91 
   92 void
   93 ipkdb_init()
   94 {
   95         ipkdbinit();
   96         if (   ipkdbifinit(&ipkdb_if) < 0
   97             || !(ipkdb_if.flags&IPKDB_MYHW)
   98             || !hmac_init()) {
   99                 /* Interface not found, drop IPKDB */
  100                 printf("IPKDB: No interface found!\n");
  101                 boothowto &= ~RB_KDB;
  102         }
  103 }
  104 
  105 void
  106 ipkdb_connect(when)
  107         int when;
  108 {
  109         boothowto |= RB_KDB;
  110         if (when == 0)
  111                 printf("waiting for remote debugger\n");
  112         ipkdb_trap();
  113 }
  114 
  115 void
  116 ipkdb_panic()
  117 {
  118         ipkdbpanic = 1;
  119         ipkdb_trap();
  120 }
  121 
  122 /*
  123  * Doesn't handle overlapping regions!
  124  */
  125 void
  126 ipkdbcopy(s, d, n)
  127         void *s, *d;
  128         int n;
  129 {
  130         char *sp = s, *dp = d;
  131 
  132         while (--n >= 0)
  133                 *dp++ = *sp++;
  134 }
  135 
  136 void
  137 ipkdbzero(d, n)
  138         void *d;
  139         int n;
  140 {
  141         char *dp = d;
  142 
  143         while (--n >= 0)
  144                 *dp++ = 0;
  145 }
  146 
  147 int
  148 ipkdbcmp(s, d, n)
  149         void *s, *d;
  150         int n;
  151 {
  152         char *sp = s, *dp = d;
  153 
  154         while (--n >= 0)
  155                 if (*sp++ != *dp++)
  156                         return *--dp - *--sp;
  157         return 0;
  158 }
  159 
  160 int
  161 ipkdbcmds()
  162 {
  163         static char buf[512];
  164         char *cp;
  165         int plen;
  166 
  167         if (!(ipkdb_if.flags&IPKDB_MYHW))       /* no interface */
  168                 return IPKDB_CMD_EXIT;
  169         init(&ipkdb_if);
  170         if (ipkdbpanic > 1) {
  171                 ipkdb_if.leave(&ipkdb_if);
  172                 return IPKDB_CMD_RUN;
  173         }
  174         putpkt(&ipkdb_if, "s", 1);
  175         while (1) {
  176                 getpkt(&ipkdb_if, buf, &plen);
  177                 if (!plen) {
  178                         if (ipkdbpanic && ipkdb_poll()) {
  179                                 ipkdb_if.leave(&ipkdb_if);
  180                                 return IPKDB_CMD_RUN;
  181                         } else
  182                                 continue;
  183                 } else
  184                         ipkdbpanic = 0;
  185                 switch (*buf) {
  186                 default:
  187                         putpkt(&ipkdb_if, "eunknown command", 16);
  188                         break;
  189                 case 'O':
  190                         /* This is an allowed reconnect, ack it */
  191                         putpkt(&ipkdb_if, "s", 1);
  192                         break;
  193                 case 'R':
  194                         peekmem(&ipkdb_if, buf, ipkdbregs, sizeof ipkdbregs);
  195                         break;
  196                 case 'W':
  197                         if (plen != sizeof ipkdbregs + 1) {
  198                                 putpkt(&ipkdb_if, "einvalid register size", 22);
  199                                 break;
  200                         }
  201                         pokemem(&ipkdb_if, buf + 1, ipkdbregs, sizeof ipkdbregs);
  202                         break;
  203                 case 'M':
  204                         {
  205                                 void *addr, *len;
  206 
  207                                 plen--;
  208                                 if (   !(cp = ipkdbaddr(buf + 1, &plen, &addr))
  209                                     || !ipkdbaddr(cp, &plen, &len)) {
  210                                         putpkt(&ipkdb_if, "einvalid peek format", 20);
  211                                         break;
  212                                 }
  213                                 peekmem(&ipkdb_if, buf, addr, (long)len);
  214                                 break;
  215                         }
  216                 case 'N':
  217                         {
  218                                 void *addr, *len;
  219 
  220                                 plen--;
  221                                 if (   !(cp = ipkdbaddr(buf + 1, &plen, &addr))
  222                                     || !(cp = ipkdbaddr(cp, &plen, &len))
  223                                     || plen < (long)len) {
  224                                         putpkt(&ipkdb_if, "einvalid poke format", 20);
  225                                         break;
  226                                 }
  227                                 pokemem(&ipkdb_if, cp, addr, (long)len);
  228                                 break;
  229                         }
  230                 case 'S':
  231                         ipkdb_if.leave(&ipkdb_if);
  232                         return IPKDB_CMD_STEP;
  233                 case 'X':
  234                         putpkt(&ipkdb_if, "ok",2);
  235                         ipkdb_if.leave(&ipkdb_if);
  236                         return IPKDB_CMD_EXIT;
  237                 case 'C':
  238                         ipkdb_if.leave(&ipkdb_if);
  239                         return IPKDB_CMD_RUN;
  240                 }
  241         }
  242 }
  243 
  244 static u_char *
  245 ipkdbaddr(cp, pl, dp)
  246         u_char *cp;
  247         int *pl;
  248         void **dp;
  249 {
  250         /* Assume that sizeof(void *) <= sizeof(u_long) */
  251         u_long l;
  252         int i;
  253 
  254         if ((*pl -= sizeof *dp) < 0)
  255                 return 0;
  256         for (i = sizeof *dp, l = 0; --i >= 0;) {
  257                 l <<= 8;
  258                 l |= *cp++;
  259         }
  260         *dp = (void *)l;
  261         return cp;
  262 }
  263 
  264 static void
  265 peekmem(ifp, buf, addr, len)
  266         struct ipkdb_if *ifp;
  267         u_char *buf;
  268         void *addr;
  269         long len;
  270 {
  271         u_char *cp, *p = addr;
  272         int l;
  273 
  274         cp = buf;
  275         *cp++ = 'p';
  276         for (l = len; --l >= 0;)
  277                 *cp++ = ipkdbfbyte(p++);
  278         putpkt(ifp, buf, len + 1);
  279 }
  280 
  281 static void
  282 pokemem(ifp, cp, addr, len)
  283         struct ipkdb_if *ifp;
  284         u_char *cp;
  285         void *addr;
  286         long len;
  287 {
  288         u_char *p = addr;
  289 
  290         while (--len >= 0)
  291                 ipkdbsbyte(p++, *cp++);
  292         putpkt(ifp, "ok", 2);
  293 }
  294 
  295 __inline static u_int32_t
  296 getnl(vs)
  297         void *vs;
  298 {
  299         u_char *s = vs;
  300 
  301         return (*s << 24)|(s[1] << 16)|(s[2] << 8)|s[3];
  302 }
  303 
  304 __inline static u_int
  305 getns(vs)
  306         void *vs;
  307 {
  308         u_char *s = vs;
  309 
  310         return (*s << 8)|s[1];
  311 }
  312 
  313 __inline static void
  314 setnl(vs, l)
  315         void *vs;
  316         u_int32_t l;
  317 {
  318         u_char *s = vs;
  319 
  320         *s++ = l >> 24;
  321         *s++ = l >> 16;
  322         *s++ = l >> 8;
  323         *s = l;
  324 }
  325 
  326 __inline static void
  327 setns(vs, l)
  328         void *vs;
  329         int l;
  330 {
  331         u_char *s = vs;
  332 
  333         *s++ = l >> 8;
  334         *s = l;
  335 }
  336 
  337 static u_short
  338 cksum(st, vcp, l)
  339         u_short st;
  340         void *vcp;
  341         int l;
  342 {
  343         u_char *cp = vcp;
  344         u_long s;
  345 
  346         for (s = st; (l -= 2) >= 0; cp += 2)
  347                 s += (*cp << 8) + cp[1];
  348         if (l == -1)
  349                 s += *cp << 8;
  350         while (s&0xffff0000)
  351                 s = (s&0xffff) + (s >> 16);
  352         return s == 0xffff ? 0 : s;
  353 }
  354 
  355 static int
  356 assemble(ifp, buf)
  357         struct ipkdb_if *ifp;
  358         void *buf;
  359 {
  360         struct ip *ip, iph;
  361         int off, len, i;
  362         u_char *cp, *ecp;
  363 
  364         ip = (struct ip *)buf;
  365         ipkdbcopy(ip, &iph, sizeof iph);
  366         iph.ip_hl = 5;
  367         iph.ip_tos = 0;
  368         iph.ip_len = 0;
  369         iph.ip_off = 0;
  370         iph.ip_ttl = 0;
  371         iph.ip_sum = 0;
  372         if (ifp->asslen) {
  373                 if (ipkdbcmp(&iph, ifp->ass, sizeof iph)) {
  374                         /*
  375                          * different packet
  376                          * decide whether to keep the old
  377                          * or start a new one
  378                          */
  379                         i = (getns(&ip->ip_id)
  380                              ^ getns(&((struct ip *)ifp->ass)->ip_id));
  381                         i ^= ((i >> 2) ^ (i >> 4) ^ (i >> 8) ^ (i >> 12));
  382                         if (i & 1)
  383                                 /* keep the old */
  384                                 return 0;
  385                         ifp->asslen = 0;
  386                 }
  387         }
  388         if (!ifp->asslen) {
  389                 ipkdbzero(ifp->assbit, sizeof ifp->assbit);
  390                 ipkdbcopy(&iph, ifp->ass, sizeof iph);
  391         }
  392         off = getns(&ip->ip_off);
  393         len = ((off & IP_OFFMASK) << 3) + getns(&ip->ip_len) - ip->ip_hl * 4;
  394         if (ifp->asslen < len)
  395                 ifp->asslen = len;
  396         if (ifp->asslen + sizeof *ip > sizeof ifp->ass) {
  397                 /* packet too long */
  398                 ifp->asslen = 0;
  399                 return 0;
  400         }
  401         if (!(off & IP_MF)) {
  402                 off &= IP_OFFMASK;
  403                 cp = ifp->assbit + (off >> 3);
  404                 for (i = (off & 7); i < 8; *cp |= 1 << i++);
  405                 for (; cp < ifp->assbit + sizeof ifp->assbit; *cp++ = -1);
  406         } else {
  407                 off &= IP_OFFMASK;
  408                 cp = ifp->assbit + (off >> 3);
  409                 ecp = ifp->assbit + (len >> 6);
  410                 if (cp == ecp)
  411                         for (i = (off & 7); i <= ((len >> 3) & 7);
  412                              *cp |= 1 << i++);
  413                 else {
  414                         for (i = (off & 7); i < 8; *cp |= 1 << i++);
  415                         for (; ++cp < ecp; *cp = -1);
  416                         for (i = 0; i < ((len >> 3) & 7); *cp |= 1 << i++);
  417                 }
  418         }
  419         ipkdbcopy((char *)buf + ip->ip_hl * 4,
  420                   ifp->ass + sizeof *ip + (off << 3),
  421                   len - (off << 3));
  422         for (cp = ifp->assbit; cp < ifp->assbit + sizeof ifp->assbit;)
  423                 if (*cp++ != (u_char)-1)
  424                         /* not complete */
  425                         return 0;
  426         ip = (struct ip *)ifp->ass;
  427         setns(&ip->ip_len, sizeof *ip + ifp->asslen);
  428         /* complete */
  429         return 1;
  430 }
  431 
  432 static char *
  433 inpkt(ifp, ibuf, poll)
  434         struct ipkdb_if *ifp;
  435         char *ibuf;
  436         int poll;
  437 {
  438         int cnt = 1000000;
  439         int l, ul;
  440         struct ether_header *eh;
  441         struct arphdr *ah;
  442         struct ip *ip;
  443         struct udphdr *udp;
  444         struct ipovly ipo;
  445 
  446         while (1) {
  447                 l = ifp->receive(ifp, ibuf, poll != 0);
  448                 if (!l) {
  449                         if (poll == 1 || (poll == 2 && --cnt <= 0))
  450                                 break;
  451                         else
  452                                 continue;
  453                 }
  454                 eh = (struct ether_header *)ibuf;
  455                 switch (getns(&eh->ether_type)) {
  456                 case ETHERTYPE_ARP:
  457                         ah = (struct arphdr *)(ibuf + 14);
  458                         if (   getns(&ah->ar_hrd) != ARPHRD_ETHER
  459                             || getns(&ah->ar_pro) != ETHERTYPE_IP
  460                             || ah->ar_hln != 6
  461                             || ah->ar_pln != 4)
  462                                 /* unsupported arp packet */
  463                                 break;
  464                         switch (getns(&ah->ar_op)) {
  465                         case ARPOP_REQUEST:
  466                                 if (   (ifp->flags&IPKDB_MYIP)
  467                                     && !ipkdbcmp(ar_tpa(ah),
  468                                                  ifp->myinetaddr,
  469                                                  sizeof ifp->myinetaddr)) {
  470                                         /* someone requested my address */
  471                                         ipkdbcopy(eh->ether_shost,
  472                                                   eh->ether_dhost,
  473                                                   sizeof eh->ether_dhost);
  474                                         ipkdbcopy(ifp->myenetaddr,
  475                                                   eh->ether_shost,
  476                                                   sizeof eh->ether_shost);
  477                                         setns(&ah->ar_op, ARPOP_REPLY);
  478                                         ipkdbcopy(ar_sha(ah),
  479                                                   ar_tha(ah),
  480                                                   ah->ar_hln);
  481                                         ipkdbcopy(ar_spa(ah),
  482                                                   ar_tpa(ah),
  483                                                   ah->ar_pln);
  484                                         ipkdbcopy(ifp->myenetaddr,
  485                                                   ar_sha(ah),
  486                                                   ah->ar_hln);
  487                                         ipkdbcopy(ifp->myinetaddr,
  488                                                   ar_spa(ah),
  489                                                   ah->ar_pln);
  490                                         ifp->send(ifp, ibuf, 74);
  491                                         continue;
  492                                 }
  493                                 break;
  494                         default:
  495                                 break;
  496                         }
  497                         break;
  498                 case ETHERTYPE_IP:
  499                         ip = (struct ip *)(ibuf + 14);
  500                         if (   ip->ip_v != IPVERSION
  501                             || ip->ip_hl < 5
  502                             || getns(&ip->ip_len) + 14 > l)
  503                                 /* invalid packet */
  504                                 break;
  505                         if (cksum(0, ip, ip->ip_hl * 4))
  506                                 /* wrong checksum */
  507                                 break;
  508                         if (ip->ip_p != IPPROTO_UDP)
  509                                 break;
  510                         if (getns(&ip->ip_off) & ~IP_DF) {
  511                                 if (!assemble(ifp, ip))
  512                                         break;
  513                                 ip = (struct ip *)ifp->ass;
  514                                 ifp->asslen = 0;
  515                         }
  516                         udp = (struct udphdr *)((char *)ip + ip->ip_hl * 4);
  517                         ul = getns(&ip->ip_len) - ip->ip_hl * 4;
  518                         if (getns(&udp->uh_ulen) != ul)
  519                                 /* invalid UDP packet length */
  520                                 break;
  521                         ipkdbcopy(ip, &ipo, sizeof ipo);
  522                         ipkdbzero(ipo.ih_x1, sizeof ipo.ih_x1);
  523                         ipo.ih_len = udp->uh_ulen;
  524                         if (   udp->uh_sum
  525                             && cksum(cksum(0, &ipo, sizeof ipo), udp, ul))
  526                                 /* wrong checksum */
  527                                 break;
  528                         if (!(ifp->flags & IPKDB_MYIP)) {
  529                                 if (   getns(&udp->uh_sport) == 67
  530                                     && getns(&udp->uh_dport) == 68
  531                                     && *(char *)(udp + 1) == 2) {
  532                                         /* this is a BOOTP reply to our ethernet address */
  533                                         /* should check a bit more?             XXX */
  534                                         char *bootp = (char *)(udp + 1);
  535                                         ipkdbcopy(bootp + 16,
  536                                                   ifp->myinetaddr,
  537                                                   sizeof ifp->myinetaddr);
  538                                         ifp->flags |= IPKDB_MYIP;
  539                                 }
  540                                 /* give caller a chance to resend his request */
  541                                 return 0;
  542                         }
  543                         if (   ipkdbcmp(&ip->ip_dst, ifp->myinetaddr, sizeof ifp->myinetaddr)
  544                             || getns(&udp->uh_dport) != IPKDBPORT)
  545                                 break;
  546                         /* so now it's a UDP packet for the debugger */
  547                         {
  548                                 /* Check for reconnect packet */
  549                                 u_char *p;
  550 
  551                                 p = (u_char *)(udp + 1);
  552                                 if (!getnl(p) && p[6] == 'O') {
  553                                         l = getns(p + 4);
  554                                         if (   l <= ul - sizeof *udp - 6
  555                                             && check_ipkdb(ifp, &ip->ip_src,
  556                                                            p, l + 6)) {
  557                                                 ipkdbcopy(&ip->ip_src,
  558                                                           ifp->hisinetaddr,
  559                                                           sizeof ifp->hisinetaddr);
  560                                                 ipkdbcopy(eh->ether_shost,
  561                                                           ifp->hisenetaddr,
  562                                                           sizeof ifp->hisenetaddr);
  563                                                 ifp->hisport = getns(&udp->uh_sport);
  564                                                 ifp->flags |= IPKDB_HISHW|IPKDB_HISIP;
  565                                                 return p;
  566                                         }
  567                                 }
  568                         }
  569                         if (   (ifp->flags&IPKDB_HISIP)
  570                             && ipkdbcmp(&ip->ip_src,
  571                                         ifp->hisinetaddr, sizeof ifp->hisinetaddr))
  572                                 /* It's a packet from someone else */
  573                                 break;
  574                         if (!(ifp->flags&IPKDB_HISIP))
  575                                 break;
  576                         return (char *)(udp + 1);
  577                 default:
  578                         /* unknown type */
  579                         break;
  580                 }
  581         }
  582         return 0;
  583 }
  584 
  585 static short ipkdb_ipid = 0;
  586 
  587 static void
  588 outpkt(ifp, in, l, srcport, dstport)
  589         struct ipkdb_if *ifp;
  590         char *in;
  591         int l;
  592         int srcport, dstport;
  593 {
  594         struct ether_header *eh;
  595         struct ip *ip;
  596         struct udphdr *udp;
  597         u_char *cp;
  598         char _obuf[ETHERMTU + 16];
  599 #define obuf    (_obuf + 2)             /* align ip data in packet */
  600         struct ipovly ipo;
  601         int i, off;
  602 
  603         ipkdbzero(_obuf, sizeof _obuf);
  604         eh = (struct ether_header *)obuf;
  605         /*
  606          * If we don't have his ethernet address, or this is a bootp request,
  607          * broadcast the packet.
  608          */
  609         if (!(ifp->flags & IPKDB_HISHW)
  610             || dstport == 67)
  611                 for (cp = eh->ether_dhost;
  612                      cp < eh->ether_dhost + sizeof eh->ether_dhost;
  613                      *cp++ = -1);
  614         else
  615                 ipkdbcopy(ifp->hisenetaddr, eh->ether_dhost, sizeof eh->ether_dhost);
  616         ipkdbcopy(ifp->myenetaddr, eh->ether_shost, sizeof eh->ether_shost);
  617         setns(&eh->ether_type, ETHERTYPE_IP);
  618         ip = (struct ip *)(obuf + 14);
  619         ip->ip_v = IPVERSION;
  620         ip->ip_hl = 5;
  621         setns(&ip->ip_id, ipkdb_ipid++);
  622         ip->ip_ttl = 255;
  623         ip->ip_p = IPPROTO_UDP;
  624         ipkdbcopy(ifp->myinetaddr, &ip->ip_src, sizeof ip->ip_src);
  625         /*
  626          * If this is a bootp request, broadcast it.
  627          */
  628         if (dstport == 67)
  629                 for (cp = (u_char *)&ip->ip_dst;
  630                      cp < (u_char *)&ip->ip_dst + sizeof ip->ip_dst;
  631                      *cp++ = -1);
  632         else
  633                 ipkdbcopy(ifp->hisinetaddr, &ip->ip_dst, sizeof ip->ip_dst);
  634         udp = (struct udphdr *)(ip + 1);
  635         setns(&udp->uh_sport, srcport);
  636         setns(&udp->uh_dport, dstport);
  637         setns(&udp->uh_ulen, l + sizeof *udp);
  638         ipkdbcopy(ip, &ipo, sizeof ipo);
  639         ipkdbzero(ipo.ih_x1, sizeof ipo.ih_x1);
  640         ipo.ih_len = udp->uh_ulen;
  641         setns(&udp->uh_sum,
  642               ~cksum(cksum(cksum(0, &ipo, sizeof ipo),
  643                            udp, sizeof *udp),
  644                      in, l));
  645         for (cp = (u_char *)(udp + 1), l += sizeof *udp, off = 0;
  646              l > 0;
  647              l -= i, in += i, off += i, cp = (u_char *)udp) {
  648                 i = l > ifp->mtu - sizeof *ip ? ((ifp->mtu - sizeof *ip) & ~7) : l;
  649                 ipkdbcopy(in, cp, i);
  650                 setns(&ip->ip_len, i + sizeof *ip);
  651                 setns(&ip->ip_off, (l > i ? IP_MF : 0) | (off >> 3));
  652                 ip->ip_sum = 0;
  653                 setns(&ip->ip_sum, ~cksum(0, ip, sizeof *ip));
  654                 if (i + sizeof *ip < ETHERMIN)
  655                         i = ETHERMIN - sizeof *ip;
  656                 ifp->send(ifp, obuf, i + sizeof *ip + 14);
  657         }
  658 #undef  obuf
  659 }
  660 
  661 static void
  662 init(ifp)
  663         struct ipkdb_if *ifp;
  664 {
  665         u_char *cp;
  666         u_char _ibuf[ETHERMTU + 16];
  667 #define ibuf    (_ibuf + 2)             /* align ip data in packet */
  668         int secs = 0;
  669 
  670         ifp->start(ifp);
  671         if (ifp->flags & IPKDB_MYIP)
  672                 return;
  673 
  674         while (!(ifp->flags & IPKDB_MYIP)) {
  675                 ipkdbzero(_ibuf, sizeof _ibuf);
  676                 cp = _ibuf;
  677                 *cp++ = 1;              /* BOOTP_REQUEST */
  678                 *cp++ = 1;              /* Ethernet hardware */
  679                 *cp++ = 6;              /* length of address */
  680                 setnl(++cp, 0x12345678); /* some random number? */
  681                 setns(cp + 4, secs++);
  682                 ipkdbcopy(ifp->myenetaddr, cp + 24, sizeof ifp->myenetaddr);
  683                 outpkt(ifp, _ibuf, 300, 68, 67);
  684                 inpkt(ifp, ibuf, 2);
  685                 if (ipkdbpanic && ipkdb_poll()) {
  686                         ipkdbpanic++;
  687                         return;
  688                 }
  689         }
  690         cp = ifp->myinetaddr;
  691         printf("My IP address is %d.%d.%d.%d\n",
  692                cp[0], cp[1], cp[2], cp[3]);
  693 #undef  ibuf
  694 }
  695 
  696 /* HMAC Checksumming routines, see draft-ietf-ipsec-hmac-md5-00.txt */
  697 #define LENCHK  16      /* Length of checksum in bytes */
  698 
  699 /*
  700  * This code is based on the MD5 implementation as found in ssh.
  701  * It's quite a bit hacked by myself, but the original has
  702  * the following non-copyright comments on it:
  703  */
  704 /* This code has been heavily hacked by Tatu Ylonen <ylo@cs.hut.fi> to
  705    make it compile on machines like Cray that don't have a 32 bit integer
  706    type. */
  707 /*
  708  * This code implements the MD5 message-digest algorithm.
  709  * The algorithm is due to Ron Rivest.  This code was
  710  * written by Colin Plumb in 1993, no copyright is claimed.
  711  * This code is in the public domain; do with it what you wish.
  712  *
  713  * Equivalent code is available from RSA Data Security, Inc.
  714  * This code has been tested against that, and is equivalent,
  715  * except that you don't need to include two pages of legalese
  716  * with every copy.
  717  */
  718 static struct ipkdb_MD5Context {
  719         u_int buf[4];
  720         u_int bits[2];
  721         u_char in[64];
  722 } icontext, ocontext;
  723 
  724 static u_int32_t getNl __P((void *));
  725 static void setNl __P((void *, u_int32_t));
  726 static void ipkdb_MD5Transform __P((struct ipkdb_MD5Context *));
  727 static void ipkdb_MD5Init __P((struct ipkdb_MD5Context *));
  728 static void ipkdb_MD5Update __P((struct ipkdb_MD5Context *, u_char *, u_int));
  729 static u_char *ipkdb_MD5Final __P((struct ipkdb_MD5Context *));
  730 
  731 __inline static u_int32_t
  732 getNl(vs)
  733         void *vs;
  734 {
  735         u_char *s = vs;
  736 
  737         return *s | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
  738 }
  739 
  740 __inline static void
  741 setNl(vs, l)
  742         void *vs;
  743         u_int32_t l;
  744 {
  745         u_char *s = vs;
  746 
  747         *s++ = l;
  748         *s++ = l >> 8;
  749         *s++ = l >> 16;
  750         *s = l >> 24;
  751 }
  752 
  753 /* The four core functions - F1 is optimized somewhat */
  754 /* #define F1(x, y, z)  (((x) & (y)) | (~(x) & (z))) */
  755 #define F1(x, y, z)     ((z) ^ ((x) & ((y) ^ (z))))
  756 #define F2(x, y, z)     F1(z, x, y)
  757 #define F3(x, y, z)     ((x) ^ (y) ^ (z))
  758 #define F4(x, y, z)     ((y) ^ ((x) | ~(z)))
  759 
  760 /* This is the central step in the MD5 algorithm. */
  761 #define ipkdb_MD5STEP(f, w, x, y, z, data, s) \
  762         ((w) += f(x, y, z) + (data), \
  763          (w) = ((w) << (s)) | (((w) >> (32 - s)) & 0xffffffff), \
  764          (w) += (x))
  765 
  766 /*
  767  * The core of the MD5 algorithm, this alters an existing MD5 hash to
  768  * reflect the addition of 16 longwords of new data.  MD5Update blocks
  769  * the data for this routine.
  770  */
  771 static void
  772 ipkdb_MD5Transform(ctx)
  773         struct ipkdb_MD5Context *ctx;
  774 {
  775         u_int a, b, c, d, i;
  776         u_int in[16];
  777         
  778         for (i = 0; i < 16; i++)
  779                 in[i] = getNl(ctx->in + 4 * i);
  780         
  781         a = ctx->buf[0];
  782         b = ctx->buf[1];
  783         c = ctx->buf[2];
  784         d = ctx->buf[3];
  785 
  786         ipkdb_MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
  787         ipkdb_MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
  788         ipkdb_MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
  789         ipkdb_MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
  790         ipkdb_MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
  791         ipkdb_MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
  792         ipkdb_MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
  793         ipkdb_MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
  794         ipkdb_MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
  795         ipkdb_MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
  796         ipkdb_MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
  797         ipkdb_MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
  798         ipkdb_MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
  799         ipkdb_MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
  800         ipkdb_MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
  801         ipkdb_MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
  802 
  803         ipkdb_MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
  804         ipkdb_MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
  805         ipkdb_MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
  806         ipkdb_MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
  807         ipkdb_MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
  808         ipkdb_MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
  809         ipkdb_MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
  810         ipkdb_MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
  811         ipkdb_MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
  812         ipkdb_MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
  813         ipkdb_MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
  814         ipkdb_MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
  815         ipkdb_MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
  816         ipkdb_MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
  817         ipkdb_MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
  818         ipkdb_MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
  819 
  820         ipkdb_MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
  821         ipkdb_MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
  822         ipkdb_MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
  823         ipkdb_MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
  824         ipkdb_MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
  825         ipkdb_MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
  826         ipkdb_MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
  827         ipkdb_MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
  828         ipkdb_MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
  829         ipkdb_MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
  830         ipkdb_MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
  831         ipkdb_MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
  832         ipkdb_MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
  833         ipkdb_MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
  834         ipkdb_MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
  835         ipkdb_MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
  836 
  837         ipkdb_MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
  838         ipkdb_MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
  839         ipkdb_MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
  840         ipkdb_MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
  841         ipkdb_MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
  842         ipkdb_MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
  843         ipkdb_MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
  844         ipkdb_MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
  845         ipkdb_MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
  846         ipkdb_MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
  847         ipkdb_MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
  848         ipkdb_MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
  849         ipkdb_MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
  850         ipkdb_MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
  851         ipkdb_MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
  852         ipkdb_MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
  853 
  854         ctx->buf[0] += a;
  855         ctx->buf[1] += b;
  856         ctx->buf[2] += c;
  857         ctx->buf[3] += d;
  858 }
  859 
  860 /*
  861  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  862  * initialization constants.
  863  */
  864 static void
  865 ipkdb_MD5Init(ctx)
  866         struct ipkdb_MD5Context *ctx;
  867 {
  868         ctx->buf[0] = 0x67452301;
  869         ctx->buf[1] = 0xefcdab89;
  870         ctx->buf[2] = 0x98badcfe;
  871         ctx->buf[3] = 0x10325476;
  872         
  873         ctx->bits[0] = 0;
  874         ctx->bits[1] = 0;
  875 }
  876 
  877 /*
  878  * Update context to reflect the concatenation of another buffer full
  879  * of bytes.
  880  */
  881 static void
  882 ipkdb_MD5Update(ctx, buf, len)
  883         struct ipkdb_MD5Context *ctx;
  884         u_char *buf;
  885         unsigned len;
  886 {
  887         u_int t;
  888 
  889         /* Update bitcount */
  890         t = ctx->bits[0];
  891         if ((ctx->bits[0] = (t + (len << 3)) & 0xffffffff) < t)
  892                 ctx->bits[1]++; /* Carry from low to high */
  893         ctx->bits[1] += (len >> 29) & 0xffffffff;
  894         
  895         t = (t >> 3) & 0x3f;    /* Bytes already in ctx->in */
  896         
  897         /* Handle any leading odd-sized chunks */
  898         if (t) {
  899                 u_char *p = ctx->in + t;
  900                 
  901                 t = 64 - t;
  902                 if (len < t) {
  903                         ipkdbcopy(buf, p, len);
  904                         return;
  905                 }
  906                 ipkdbcopy(buf, p, t);
  907                 ipkdb_MD5Transform(ctx);
  908                 buf += t;
  909                 len -= t;
  910         }
  911         
  912         /* Process data in 64-byte chunks */
  913         while (len >= 64) {
  914                 ipkdbcopy(buf, ctx->in, 64);
  915                 ipkdb_MD5Transform(ctx);
  916                 buf += 64;
  917                 len -= 64;
  918         }
  919         
  920         /* Handle any remaining bytes of data. */
  921         ipkdbcopy(buf, ctx->in, len);
  922 }
  923 
  924 /*
  925  * Final wrapup - pad to 64-byte boundary with the bit pattern
  926  * 1 0* (64-bit count of bits processed, LSB-first)
  927  */
  928 static u_char *
  929 ipkdb_MD5Final(ctx)
  930         struct ipkdb_MD5Context *ctx;
  931 {
  932         static u_char digest[16];
  933         unsigned count;
  934         u_char *p;
  935         
  936         /* Compute number of bytes mod 64 */
  937         count = (ctx->bits[0] >> 3) & 0x3f;
  938         
  939         /* Set the first char of padding to 0x80.  This is safe since there is
  940            always at least one byte free */
  941         p = ctx->in + count;
  942         *p++ = 0x80;
  943         
  944         /* Bytes of padding needed to make 64 bytes */
  945         count = 64 - 1 - count;
  946         
  947         /* Pad out to 56 mod 64 */
  948         if (count < 8) {
  949                 /* Two lots of padding:  Pad the first block to 64 bytes */
  950                 ipkdbzero(p, count);
  951                 ipkdb_MD5Transform(ctx);
  952                 
  953                 /* Now fill the next block with 56 bytes */
  954                 ipkdbzero(ctx->in, 56);
  955         } else
  956                 /* Pad block to 56 bytes */
  957                 ipkdbzero(p, count - 8);
  958         
  959         /* Append length in bits and transform */
  960         setNl(ctx->in + 56, ctx->bits[0]);
  961         setNl(ctx->in + 60, ctx->bits[1]);
  962         
  963         ipkdb_MD5Transform(ctx);
  964         setNl(digest, ctx->buf[0]);
  965         setNl(digest + 4, ctx->buf[1]);
  966         setNl(digest + 8, ctx->buf[2]);
  967         setNl(digest + 12, ctx->buf[3]);
  968 
  969         return digest;
  970 }
  971 
  972 /*
  973  * The following code is more or less stolen from the hmac_md5
  974  * function in the Appendix of the HMAC IETF draft, but is
  975  * optimized as suggested in this same paper.
  976  */
  977 static int
  978 hmac_init()
  979 {
  980         char pad[64];
  981         char tk[16];
  982         u_char *key = ipkdbkey;
  983         int key_len = strlen(key);
  984         int i;
  985 
  986         /* Require key to be at least 16 bytes long */
  987         if (key_len < 16) {
  988                 printf("IPKDBKEY must be at least 16 bytes long!\n");
  989                 ipkdbzero(key, key_len);                                /* XXX */
  990                 return 0;
  991         }
  992 
  993         /* if key is longer than 64 bytes reset it to key=MD5(key) */
  994         if (key_len > 64) {
  995                 ipkdb_MD5Init(&icontext);
  996                 ipkdb_MD5Update(&icontext, key, key_len);
  997                 ipkdbcopy(ipkdb_MD5Final(&icontext), tk, 16);
  998                 ipkdbzero(key, key_len);                                /* XXX */
  999                 key = tk;
 1000                 key_len = 16;
 1001         }
 1002 
 1003         /*
 1004          * the HMAC_MD5 transform looks like:
 1005          *
 1006          * MD5(K XOR opad, MD5(K XOR ipad, text))
 1007          *
 1008          * where K is and n byte key
 1009          * ipad is the byte 0x36 repeated 64 times
 1010          * opad is the byte 0x5c repeated 64 times
 1011          * and text is the data being protected
 1012          */
 1013         /*
 1014          * We do the initial part of MD5(K XOR ipad)
 1015          * and MD5(K XOR opad) here, in order to
 1016          * speed up the computation later on.
 1017          */
 1018         ipkdbzero(pad, sizeof pad);
 1019         ipkdbcopy(key, pad, key_len);
 1020         for (i = 0; i < 64; i++)
 1021                 pad[i] ^= 0x36;
 1022         ipkdb_MD5Init(&icontext);
 1023         ipkdb_MD5Update(&icontext, pad, 64);
 1024         
 1025         ipkdbzero(pad, sizeof pad);
 1026         ipkdbcopy(key, pad, key_len);
 1027         for (i = 0; i < 64; i++)
 1028                 pad[i] ^= 0x5c;
 1029         ipkdb_MD5Init(&ocontext);
 1030         ipkdb_MD5Update(&ocontext, pad, 64);
 1031 
 1032         /* Zero out the key                                             XXX */
 1033         ipkdbzero(key, key_len);
 1034 
 1035         return 1;
 1036 }
 1037 
 1038 /*
 1039  * This is more or less hmac_md5 from the HMAC IETF draft, Appendix.
 1040  */
 1041 static void *
 1042 chksum(buf, len)
 1043         void *buf;
 1044         int len;
 1045 {
 1046         u_char *digest;
 1047         struct ipkdb_MD5Context context;
 1048         
 1049         /*
 1050          * the HMAC_MD5 transform looks like:
 1051          *
 1052          * MD5(K XOR opad, MD5(K XOR ipad, text))
 1053          *
 1054          * where K is an n byte key
 1055          * ipad is the byte 0x36 repeated 64 times
 1056          * opad is the byte 0x5c repeated 64 times
 1057          * and text is the data being protected
 1058          */
 1059         /*
 1060          * Since we've already done the precomputation,
 1061          * we can now stuff the data into the relevant
 1062          * preinitialized contexts to get the result.
 1063          */
 1064         /*
 1065          * perform inner MD5
 1066          */
 1067         ipkdbcopy(&icontext, &context, sizeof context);
 1068         ipkdb_MD5Update(&context, buf, len);
 1069         digest = ipkdb_MD5Final(&context);
 1070         /*
 1071          * perform outer MD5
 1072          */
 1073         ipkdbcopy(&ocontext, &context, sizeof context);
 1074         ipkdb_MD5Update(&context, digest, 16);
 1075         return ipkdb_MD5Final(&context);
 1076 }
 1077 
 1078 static void
 1079 getpkt(ifp, buf, lp)
 1080         struct ipkdb_if *ifp;
 1081         char *buf;
 1082         int *lp;
 1083 {
 1084         char *got;
 1085         int l;
 1086         char _ibuf[ETHERMTU + 16];
 1087 #define ibuf    (_ibuf + 2)             /* align ip data in packet */
 1088 
 1089         *lp = 0;
 1090         while (1) {
 1091                 if (!(got = inpkt(ifp, ibuf, ipkdbpanic != 0))) {
 1092                         *lp = 0;
 1093                         return;
 1094                 }
 1095                 if (   ifp->seq == getnl(got)
 1096                     && got[6] >= 'A'
 1097                     && got[6] <= 'Z'
 1098                     && (l = getns(got + 4))
 1099                     && !ipkdbcmp(chksum(got, l + 6), got + l + 6, LENCHK)) {
 1100                         ipkdbcopy(got + 6, buf, *lp = l);
 1101                         return;
 1102                 }
 1103                 if (   ifp->pktlen
 1104                     && ((ifp->flags & (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
 1105                         == (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED)))
 1106                         outpkt(ifp, ifp->pkt, ifp->pktlen, IPKDBPORT, ifp->hisport);
 1107         }
 1108 #undef  ibuf
 1109 }
 1110 
 1111 static void
 1112 putpkt(ifp, buf, l)
 1113         struct ipkdb_if *ifp;
 1114         char *buf;
 1115         int l;
 1116 {
 1117         setnl(ifp->pkt, ifp->seq++);
 1118         setns(ifp->pkt + 4, l);
 1119         ipkdbcopy(buf, ifp->pkt + 6, l);
 1120         ipkdbcopy(chksum(ifp->pkt, l + 6), ifp->pkt + 6 + l, LENCHK);
 1121         ifp->pktlen = l + 6 + LENCHK;
 1122         if (   (ifp->flags & (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
 1123             != (IPKDB_MYIP | IPKDB_HISIP | IPKDB_CONNECTED))
 1124                 return;
 1125         outpkt(ifp, ifp->pkt, ifp->pktlen, IPKDBPORT, ifp->hisport);
 1126 }
 1127 
 1128 static int
 1129 check_ipkdb(ifp, shost, p, l)
 1130         struct ipkdb_if *ifp;
 1131         struct in_addr *shost;
 1132         char *p;
 1133         int l;
 1134 {
 1135         u_char hisenet[6];
 1136         u_char hisinet[4];
 1137         u_int16_t hisport;
 1138         char save;
 1139 
 1140 #ifndef IPKDBSECURE
 1141         if (securelevel > 0)
 1142                 return 0;
 1143 #endif
 1144         if (ipkdbcmp(chksum(p, l), p + l, LENCHK))
 1145                 return 0;
 1146         ipkdbcopy(ifp->hisenetaddr, hisenet, sizeof hisenet);
 1147         ipkdbcopy(ifp->hisinetaddr, hisinet, sizeof hisinet);
 1148         hisport = ifp->hisport;
 1149         save = ifp->flags;
 1150         ipkdbcopy(shost, ifp->hisinetaddr, sizeof ifp->hisinetaddr);
 1151         ifp->flags &= ~IPKDB_HISHW;
 1152         ifp->flags |= IPKDB_HISIP;
 1153         if (connectipkdb(ifp, p + 6, l - 6) < 0) {
 1154                 ipkdbcopy(hisenet, ifp->hisenetaddr, sizeof ifp->hisenetaddr);
 1155                 ipkdbcopy(hisinet, ifp->hisinetaddr, sizeof ifp->hisinetaddr);
 1156                 ifp->hisport = hisport;
 1157                 ifp->flags = save;
 1158                 return 0;
 1159         }
 1160         return 1;
 1161 }
 1162 
 1163 /*
 1164  * Should check whether packet came across the correct interface.       XXX
 1165  */
 1166 int
 1167 checkipkdb(shost, sport, dport, m, off, len)
 1168         struct in_addr *shost;
 1169         u_short sport, dport;
 1170         struct mbuf *m;
 1171         int off, len;
 1172 {
 1173         char *p;
 1174         int l;
 1175         char ibuf[ETHERMTU+50];
 1176 
 1177         if (dport != IPKDBPORT)
 1178                 return 0;
 1179         if (len > sizeof ibuf)
 1180                 return 0;
 1181         m_copydata(m, off, len, ibuf);
 1182         p = ibuf;
 1183         if (getnl(p) || p[6] != 'O')
 1184                 return 0;
 1185         l = getns(p + 4);
 1186         if (l > len - 6 || !check_ipkdb(&ipkdb_if, shost, p, l + 6))
 1187                 return 0;
 1188         ipkdb_if.hisport = sport;
 1189         ipkdb_connect(1);
 1190         return 1;
 1191 }
 1192 
 1193 static int
 1194 connectipkdb(ifp, buf, l)
 1195         struct ipkdb_if *ifp;
 1196         char *buf;
 1197         int l;
 1198 {
 1199         char *cp;
 1200         u_char *ip;
 1201 
 1202         if (*buf != 'O')
 1203                 return -1;
 1204         if (getnl(buf + 1) == ifp->id)
 1205                 /* It's a retry of a connect packet, ignore it */
 1206                 return -1;
 1207         ip = ifp->hisinetaddr;
 1208         printf("debugged by ");
 1209         l -= 1 + sizeof(u_int32_t);
 1210         for (cp = buf + 1 + sizeof(u_int32_t); --l >= 0; printf("%c", *cp++));
 1211         printf(" (%d.%d.%d.%d)\n", ip[0], ip[1], ip[2], ip[3]);
 1212         ifp->flags |= IPKDB_CONNECTED;
 1213         ifp->seq = 0;
 1214         ifp->pktlen = 0;
 1215         ifp->id = getnl(buf + 1);
 1216         return 0;
 1217 }

Cache object: cd6b045259278d05ae7182a06cf1d5d7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.