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

Cache object: 6d7ce9326ca7633798e64cc71e8b6636


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