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