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