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  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 25c6271696b203a6425de02271822f4b


[ 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.