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