1 #ifdef RCSIDENT
2 static char rcsident[] = "$Header: in.c,v 1.28 85/04/08 15:06:03 walsh Exp $";
3 #endif
4
5 #include "../h/param.h"
6 #include "../h/mbuf.h"
7 #include "../h/protosw.h"
8 #include "../h/socket.h"
9 #include "../h/socketvar.h"
10 #include "../h/errno.h"
11 #include "../h/ioctl.h"
12 #include "../h/dir.h"
13 #include "../h/user.h"
14
15 #include "../net/if.h"
16 #include "../net/route.h"
17 #include "../net/af.h"
18 #include "../net/netisr.h"
19 #include "../vax/mtpr.h"
20
21 #include "../bbnnet/in.h"
22 #include "../bbnnet/net.h"
23 #include "../bbnnet/in_pcb.h"
24 #include "../bbnnet/in_var.h"
25 #include "../bbnnet/fsm.h"
26 #include "../bbnnet/tcp.h"
27 #include "../bbnnet/udp.h"
28 #include "../bbnnet/ip.h"
29 #include "../bbnnet/icmp.h"
30
31 #ifdef BBNNET
32
33 struct in_ifaddr *in_ifaddr; /* list of Internet addresses for interfaces */
34
35 #define IN_CLASSA(i) ((((long)(i))&0x80000000)==0)
36 #define IN_CLASSA_NET 0xff000000
37 #define IN_CLASSA_NSHIFT 24
38 #define IN_CLASSA_HOST 0x00ffffff
39
40 #define IN_CLASSB(i) ((((long)(i))&0xc0000000)==0x80000000)
41 #define IN_CLASSB_NET 0xffff0000
42 #define IN_CLASSB_NSHIFT 16
43 #define IN_CLASSB_HOST 0x0000ffff
44
45 #define IN_CLASSC(i) ((((long)(i))&0xc0000000)==0xc0000000)
46 #define IN_CLASSC_NET 0xffffff00
47 #define IN_CLASSC_NSHIFT 8
48 #define IN_CLASSC_HOST 0x000000ff
49 /*
50 * little utility routines
51 * cannot be macros because called from non-IP segments of the code.
52 */
53
54 in_lnaof(ip_addr)
55 struct in_addr ip_addr;
56 {
57 /*
58 * 1/27/84 Berkeley interface of programs to kernel uses net ordering
59 * This subr used for SIOCSIFADDR ioctl
60 */
61 register u_long i = ntohl(ip_addr.s_addr);
62
63 if (IN_CLASSA(i))
64 return ((i)&IN_CLASSA_HOST);
65 else if (IN_CLASSB(i))
66 return ((i)&IN_CLASSB_HOST);
67 else
68 return ((i)&IN_CLASSC_HOST);
69 }
70
71 /*
72 #ifdef unused
73 */
74 in_netof(ip_addr)
75 struct in_addr ip_addr;
76 {
77 register u_long i = ntohl(ip_addr.s_addr);
78
79 if (IN_CLASSA(i))
80 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
81 else if (IN_CLASSB(i))
82 return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
83 else
84 return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
85 }
86 /*
87 #endif
88 */
89
90 /*
91 * hash an internet address for routing lookups
92 * host part of the address is byte-swapped to put host-specific
93 * bits in the low byte (only the low LOG2(RTHASHSIZ) bits are used by rtalloc)
94 */
95
inet_hash(sin,hp)96 inet_hash(sin, hp)
97 register struct sockaddr_in *sin;
98 struct afhash *hp;
99 {
100 hp->afh_nethash = NETHASH(sin->sin_addr);
101 hp->afh_hosthash = HOSTHASH(sin->sin_addr.s_addr);
102 }
103
104 inet_netmatch(sin1, sin2)
105 struct sockaddr_in *sin1, *sin2;
106 {
107
108 return (iptonet(sin1->sin_addr) == iptonet(sin2->sin_addr));
109 }
110
111 /*
112 * Formulate an Internet address from network + host.
113 */
in_makeaddr(net,host)114 struct in_addr in_makeaddr(net, host)
115 u_long net, host;
116 {
117 register struct in_ifaddr *ia;
118 register u_long mask;
119 u_long addr;
120
121 if (IN_CLASSA(net))
122 mask = IN_CLASSA_HOST;
123 else if (IN_CLASSB(net))
124 mask = IN_CLASSB_HOST;
125 else
126 mask = IN_CLASSC_HOST;
127
128 for (ia = in_ifaddr; ia; ia = ia->ia_next)
129 if ((ia->ia_netmask & net) == ia->ia_net)
130 {
131 mask = ~ia->ia_subnetmask;
132 break;
133 }
134
135 addr = htonl(net | (host & mask));
136 return (*(struct in_addr *)&addr);
137 }
138
139 /*
140 * Return 1 if the address is a local broadcast address.
141 */
142 in_broadcast(in)
143 struct in_addr in;
144 {
145 register struct in_ifaddr *ia;
146
147 /*
148 * Look through the list of addresses for a match
149 * with a broadcast address.
150 */
151 for (ia = in_ifaddr; ia; ia = ia->ia_next)
152 if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr ==
153 in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST))
154 return (TRUE);
155 return (FALSE);
156 }
157
158 /*
159 * Return the network number from an internet address.
160 */
161 iptonet (in)
162 struct in_addr in;
163 {
164 register u_long i = ntohl(in.s_addr);
165 register u_long net;
166 register struct in_ifaddr *ia;
167
168 if (IN_CLASSA(i))
169 net = i & IN_CLASSA_NET;
170 else if (IN_CLASSB(i))
171 net = i & IN_CLASSB_NET;
172 else
173 net = i & IN_CLASSC_NET;
174
175 /*
176 * Check whether network is a subnet;
177 * if so, return subnet number.
178 */
179 for (ia = in_ifaddr; ia; ia = ia->ia_next)
180 if (net == ia->ia_net)
181 return (i & ia->ia_subnetmask);
182
183 return (net);
184 }
185
186 #ifdef unused
187 /*
188 * Return the host portion of an internet address.
189 */
190 iptohost (in)
191 struct in_addr in;
192 {
193 register u_long i = ntohl(in.s_addr);
194 register u_long net, host;
195 register struct in_ifaddr *ia;
196
197 if (IN_CLASSA(i))
198 {
199 net = i & IN_CLASSA_NET;
200 host = i & IN_CLASSA_HOST;
201 }
202 else if (IN_CLASSB(i))
203 {
204 net = i & IN_CLASSB_NET;
205 host = i & IN_CLASSB_HOST;
206 }
207 else
208 {
209 net = i & IN_CLASSC_NET;
210 host = i & IN_CLASSC_HOST;
211 }
212
213 /*
214 * Check whether network is a subnet;
215 * if so, use the modified interpretation of `host'.
216 */
217 for (ia = in_ifaddr; ia; ia = ia->ia_next)
218 if (net == ia->ia_net)
219 return (host & ~ia->ia_subnetmask);
220
221 return (host);
222 }
223 #endif
224
225 #ifdef unused
226 /*
227 * Return TRUE if an internet address is for a ``local'' host
228 * (one to which we have a connection through a local logical net).
229 */
230 in_localaddr(in)
231 struct in_addr in;
232 {
233 register u_long i = ntohl(in.s_addr);
234 register u_long net;
235 register struct in_ifaddr *ia;
236
237 if (IN_CLASSA(i))
238 net = i & IN_CLASSA_NET;
239 else if (IN_CLASSB(i))
240 net = i & IN_CLASSB_NET;
241 else
242 net = i & IN_CLASSC_NET;
243
244 for (ia = in_ifaddr; ia; ia = ia->ia_next)
245 if (net == ia->ia_net)
246 return (TRUE);
247
248 return (FALSE);
249 }
250 #endif
251
252 /*
253 * because defaults are a bit messy here, the ARP and interface layers
254 * are both handled here....
255 */
256
257 /* ARGSUSED */
in_ioctl(optname,optval)258 in_ioctl(optname, optval)
259 int optname;
260 struct mbuf **optval;
261 {
262 extern struct ifnet *ifunit();
263 register struct ifreq *ifr = (struct ifreq *)optval;
264 register struct ifnet *ifp = ifunit(ifr->ifr_name);
265 register struct in_ifaddr *ia = NULL;
266 struct ifaddr *ifa;
267 struct mbuf *m;
268 int error = 0;
269
270 /*
271 * ARP
272 */
273 switch (optname)
274 {
275 case SIOCSARP:
276 case SIOCDARP:
277 if (!suser())
278 return(u.u_error);
279
280 /* fall thru */
281
282 case SIOCGARP:
283 return(arpioctl(optname,(caddr_t)optval));
284 }
285
286 /*
287 * Find address for this interface, if it exists.
288 */
289 if (ifp)
290 for (ia = in_ifaddr; ia; ia = ia->ia_next)
291 if (ia->ia_ifp == ifp)
292 break;
293
294 /*
295 * Interface stuff
296 */
297
298 switch (optname)
299 {
300
301 case SIOCGIFADDR:
302 case SIOCGIFBRDADDR:
303 case SIOCGIFDSTADDR:
304 case SIOCGIFNETMASK:
305 if (ia == (struct in_ifaddr *) NULL)
306 return(EADDRNOTAVAIL);
307 break;
308
309 case SIOCSIFADDR:
310 case SIOCSIFDSTADDR:
311 case SIOCSIFBRDADDR:
312 case SIOCSIFNETMASK:
313 if (!suser())
314 return(u.u_error);
315
316 if (ifp == NULL)
317 panic("in_control");
318 if (ia == (struct in_ifaddr *) NULL)
319 {
320 m = m_getclr(M_WAIT, MT_IFADDR);
321 if (m == (struct mbuf *)NULL)
322 return(ENOBUFS);
323 if (ia = in_ifaddr)
324 {
325 for ( ; ia->ia_next; ia = ia->ia_next)
326 ;
327 ia->ia_next = mtod(m, struct in_ifaddr *);
328 }
329 else
330 in_ifaddr = mtod(m, struct in_ifaddr *);
331 ia = mtod(m, struct in_ifaddr *);
332 if (ifa = ifp->if_addrlist)
333 {
334 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
335 ;
336 ifa->ifa_next = (struct ifaddr *) ia;
337 }
338 else
339 ifp->if_addrlist = (struct ifaddr *) ia;
340 ia->ia_ifp = ifp;
341 IA_SIN(ia)->sin_family = AF_INET;
342 }
343 break;
344 }
345
346 switch (optname)
347 {
348
349 case SIOCGIFADDR:
350 ifr->ifr_addr = ia->ia_addr;
351 break;
352
353 case SIOCGIFBRDADDR:
354 if ((ifp->if_flags & IFF_BROADCAST) == 0)
355 return(EINVAL);
356 ifr->ifr_dstaddr = ia->ia_broadaddr;
357 break;
358
359 case SIOCGIFDSTADDR:
360 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
361 return(EINVAL);
362 ifr->ifr_dstaddr = ia->ia_dstaddr;
363 break;
364
365 case SIOCGIFNETMASK:
366 #define satosin(sa) ((struct sockaddr_in *)(sa))
367 satosin(&ifr->ifr_addr)->sin_family = AF_INET;
368 satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask);
369 break;
370
371 case SIOCSIFDSTADDR:
372 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
373 return(EINVAL);
374
375 if (ifp->if_ioctl &&
376 (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia)))
377 return(error);
378
379 ia->ia_dstaddr = ifr->ifr_dstaddr;
380 break;
381
382 case SIOCSIFBRDADDR:
383 if ((ifp->if_flags & IFF_BROADCAST) == 0)
384 return(EINVAL);
385
386 ia->ia_broadaddr = ifr->ifr_broadaddr;
387 break;
388
389 case SIOCSIFADDR:
390 return(in_ifinit(ifp, ia, (struct sockaddr_in *)&ifr->ifr_addr));
391
392 case SIOCSIFNETMASK:
393 ia->ia_subnetmask =
394 ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr);
395 break;
396
397 default:
398 if (ifp == NULL || ifp->if_ioctl == 0)
399 return(EOPNOTSUPP);
400
401 return(((*ifp->if_ioctl)(ifp, optname, (caddr_t)optval)));
402 }
403
404 return (0);
405 }
406
407 /*
408 * Initialize an interface's internet address
409 * and routing table entry.
410 */
in_ifinit(ifp,ia,sin)411 in_ifinit(ifp, ia, sin)
412 register struct ifnet *ifp;
413 register struct in_ifaddr *ia;
414 struct sockaddr_in *sin;
415 {
416 register u_long i = ntohl(sin->sin_addr.s_addr);
417 struct sockaddr_in netaddr;
418 int s = splimp(), error;
419
420 bzero((caddr_t)&netaddr, sizeof (netaddr));
421 netaddr.sin_family = AF_INET;
422 /*
423 * Delete any previous route for an old address.
424 */
425 if (ia->ia_flags & IFA_ROUTE)
426 {
427 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
428 {
429 netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
430 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1);
431 }
432 else
433 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1);
434 ia->ia_flags &= ~IFA_ROUTE;
435 }
436 ia->ia_addr = *(struct sockaddr *)sin;
437 if (IN_CLASSA(i))
438 ia->ia_netmask = IN_CLASSA_NET;
439 else if (IN_CLASSB(i))
440 ia->ia_netmask = IN_CLASSB_NET;
441 else
442 ia->ia_netmask = IN_CLASSC_NET;
443 ia->ia_net = i & ia->ia_netmask;
444 /*
445 * The subnet mask includes at least the standard network part,
446 * but may already have been set to a larger value.
447 */
448 ia->ia_subnetmask |= ia->ia_netmask;
449 ia->ia_subnet = i & ia->ia_subnetmask;
450 if (ifp->if_flags & IFF_BROADCAST)
451 {
452 ia->ia_broadaddr.sa_family = AF_INET;
453 satoipa(&ia->ia_broadaddr) = in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
454 }
455
456 /*
457 * Give the interface a chance to initialize
458 * if this is its first address,
459 * and to validate the address if necessary.
460 */
461 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia)))
462 {
463 splx(s);
464 bzero((caddr_t)&ia->ia_addr, sizeof(ia->ia_addr));
465 return (error);
466 }
467 splx(s);
468 /*
469 * Add route for the network.
470 */
471 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
472 {
473 netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
474 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP);
475 }
476 else
477 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, RTF_HOST|RTF_UP);
478 ia->ia_flags |= IFA_ROUTE;
479 return (0);
480 }
481
482 /*
483 * return address info for specified address
484 */
485
in_iawithaddr(addr,bcast)486 struct in_ifaddr *in_iawithaddr(addr,bcast)
487 struct in_addr addr;
488 int bcast; /* look for broadcast addrs */
489 {
490 register struct in_ifaddr *ia;
491
492 for (ia = in_ifaddr; ia; ia = ia->ia_next)
493 {
494 if (IA_INADDR(ia).s_addr == addr.s_addr)
495 return(ia);
496
497 if (bcast)
498 if (IA_B_INADDR(ia).s_addr == addr.s_addr)
499 return(ia);
500 }
501
502 return(ia);
503 }
504
in_iawithnet(addr)505 struct in_ifaddr *in_iawithnet(addr)
506 struct in_addr addr;
507 {
508 register struct in_ifaddr *ia;
509 register u_long net;
510
511 net = iptonet(addr);
512
513 for(ia = in_ifaddr; ia; ia = ia->ia_next)
514 {
515 if (iptonet(IA_INADDR(ia)) == net)
516 return(ia);
517 }
518
519 return(ia);
520 }
521
in_iafromif(ifp)522 struct in_ifaddr *in_iafromif(ifp)
523 struct ifnet *ifp;
524 {
525 register struct ifaddr *ifa;
526
527 for(ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next)
528 if (ifa->ifa_addr.sa_family == AF_INET)
529 break;
530
531 return((struct in_ifaddr *)ifa);
532 }
533
534 /*
535 #ifdef unused
536 */
537 /*
538 * Return address info for specified internet network.
539 */
in_iaonnetof(net)540 struct in_ifaddr *in_iaonnetof(net)
541 u_long net;
542 {
543 register struct in_ifaddr *ia;
544
545 for (ia = in_ifaddr; ia; ia = ia->ia_next)
546 if (ia->ia_subnet == net)
547 return (ia);
548
549 return ((struct in_ifaddr *) NULL);
550 }
551 /*
552 #endif
553 */
554 #endif
555