handle route caching here.
[unix-history] / usr / src / sys / netns / ns.c
CommitLineData
8ae0e4b4
KM
1/*
2 * Copyright (c) 1982 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
f97be0c9 6 * @(#)ns.c 6.4 (Berkeley) %G%
8ae0e4b4 7 */
de9bc7de
KS
8
9#include "param.h"
10#include "mbuf.h"
11#include "ioctl.h"
12#include "protosw.h"
13#include "socket.h"
14#include "socketvar.h"
15#include "uio.h"
16#include "dir.h"
17#include "user.h"
18
19
20#include "../net/if.h"
21#include "../net/route.h"
22#include "../net/af.h"
23
24#include "ns.h"
25#include "ns_if.h"
26
27#ifdef NS
28
29struct ns_ifaddr *ns_ifaddr;
30
31ns_hash(sns, hp)
32 register struct sockaddr_ns *sns;
33 struct afhash *hp;
34{
35 register long hash = 0;
36 register u_short *s = sns->sns_addr.x_host.s_host;
37
38 hp->afh_nethash = ns_netof(sns->sns_addr);
39 hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
40 hp->afh_hosthash = hash;
41}
42
43
44ns_netmatch(sns1, sns2)
45 struct sockaddr_ns *sns1, *sns2;
46{
47
48 return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr));
49}
50
51/*
52 * Generic internet control operations (ioctl's).
53 */
f97be0c9 54/* ARGSUSED */
de9bc7de
KS
55ns_control(so, cmd, data, ifp)
56 struct socket *so;
57 int cmd;
58 caddr_t data;
59 register struct ifnet *ifp;
60{
61 register struct ifreq *ifr = (struct ifreq *)data;
62 register struct ns_ifaddr *ia;
63 struct ifaddr *ifa;
64 struct mbuf *m;
de9bc7de 65
de9bc7de
KS
66 /*
67 * Find address for this interface, if it exists.
68 */
4353fa68
KS
69 if (ifp==0)
70 return (EADDRNOTAVAIL);
de9bc7de
KS
71 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
72 if (ia->ia_ifp == ifp)
73 break;
74
75 switch (cmd) {
76
77 case SIOCGIFADDR:
4353fa68
KS
78 if (ia == (struct ns_ifaddr *)0)
79 return (EADDRNOTAVAIL);
80 ifr->ifr_addr = ia->ia_addr;
81 return (0);
82
83
de9bc7de 84 case SIOCGIFBRDADDR:
4353fa68
KS
85 if (ia == (struct ns_ifaddr *)0)
86 return (EADDRNOTAVAIL);
87 if ((ifp->if_flags & IFF_BROADCAST) == 0)
88 return (EINVAL);
89 ifr->ifr_dstaddr = ia->ia_broadaddr;
90 return (0);
91
de9bc7de
KS
92 case SIOCGIFDSTADDR:
93 if (ia == (struct ns_ifaddr *)0)
94 return (EADDRNOTAVAIL);
4353fa68
KS
95 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
96 return (EINVAL);
97 ifr->ifr_dstaddr = ia->ia_dstaddr;
98 return (0);
99 }
100
101 if (!suser())
102 return (u.u_error);
103
104 switch (cmd) {
de9bc7de
KS
105
106 case SIOCSIFDSTADDR:
107 return (EOPNOTSUPP);
108
109 case SIOCSIFADDR:
110 if (ia == (struct ns_ifaddr *)0) {
111 m = m_getclr(M_WAIT, MT_IFADDR);
112 if (m == (struct mbuf *)NULL)
113 return (ENOBUFS);
114 if (ia = ns_ifaddr) {
115 for ( ; ia->ia_next; ia = ia->ia_next)
116 ;
117 ia->ia_next = mtod(m, struct ns_ifaddr *);
118 } else
119 ns_ifaddr = mtod(m, struct ns_ifaddr *);
120 ia = mtod(m, struct ns_ifaddr *);
121 if (ifa = ifp->if_addrlist) {
122 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
123 ;
124 ifa->ifa_next = (struct ifaddr *) ia;
125 } else
126 ifp->if_addrlist = (struct ifaddr *) ia;
127 ia->ia_ifp = ifp;
128 IA_SNS(ia)->sns_family = AF_NS;
129 }
de9bc7de
KS
130 return
131 (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr));
132
133 default:
134 if (ifp->if_ioctl == 0)
135 return (EOPNOTSUPP);
136 return ((*ifp->if_ioctl)(ifp, cmd, data));
137 }
de9bc7de
KS
138}
139
140/*
141 * Initialize an interface's internet address
142 * and routing table entry.
143 */
144ns_ifinit(ifp, ia, sns)
145 register struct ifnet *ifp;
146 register struct ns_ifaddr *ia;
147 struct sockaddr_ns *sns;
148{
149 struct sockaddr_ns netaddr;
150 register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host);
151 int s = splimp(), error;
152
153 /*
154 * The convention we shall adopt for naming is that
155 * a supplied address of zero means that "we don't care".
156 * if there is a single interface, use the address of that
157 * interface as our 6 byte host address.
158 * if there are multiple interfaces, use any address already
159 * used.
160 *
161 * If we have gotten into trouble and want to reset back to
162 * virginity, we recognize a request of the broadcast address.
163 */
164 if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) {
165 ns_thishost = ns_zerohost;
166 splx(s);
167 return(EINVAL);
168 }
169
170 /*
171 * Delete any previous route for an old address.
172 */
173
174 bzero((caddr_t)&netaddr, sizeof (netaddr));
175 netaddr.sns_family = AF_NS;
176 netaddr.sns_addr.x_host = ns_broadhost;
177 netaddr.sns_addr.x_net = ia->ia_net;
178 if (ia->ia_flags & IFA_ROUTE) {
179 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
180 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1);
181 } else
182 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1);
183 }
184
185 /*
186 * Set up new addresses.
187 */
188 ia->ia_addr = *(struct sockaddr *)sns;
189 ia->ia_net = sns->sns_addr.x_net;
190 netaddr.sns_addr.x_net = ia->ia_net;
191 if (ifp->if_flags & IFF_BROADCAST) {
192 ia->ia_broadaddr = * (struct sockaddr *) &netaddr;
193 }
194 /*
195 * Point to point links are a little touchier --
196 * We have to have an address of our own first,
197 * and will use the supplied address as that of the other end.
198 */
199 if (ifp->if_flags & IFF_POINTOPOINT) {
200 struct sockaddr_ns *sns2 = IA_SNS(ia);
201 if (ns_hosteqnh(ns_zerohost,ns_thishost))
202 return(EINVAL);
203 ia->ia_dstaddr = ia->ia_addr;
204 sns2->sns_addr.x_host = ns_thishost;
205 sns->sns_addr.x_host = ns_thishost;
206 }
207 /*
208 * Give the interface a chance to initialize
209 * if this is its first address,
210 * and to validate the address if necessary.
211 */
212
213 if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
214 if (ifp->if_ioctl &&
215 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
216 splx(s);
217 return (error);
218 }
219 ns_thishost = *h;
220 } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
221 || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
222 *h = ns_thishost;
223 if (ifp->if_ioctl &&
224 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
225 splx(s);
226 return (error);
227 }
228 if(!ns_hosteqnh(ns_thishost,*h)) {
229 splx(s);
230 return (EINVAL);
231 }
232 } else {
233 splx(s);
234 return(EINVAL);
235 }
236 /*
237 * Add route for the network.
238 */
239 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
240 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP);
241 } else
242 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
243 RTF_HOST|RTF_UP);
244 ia->ia_flags |= IFA_ROUTE;
245 return(0);
246}
247
248/*
249 * Return address info for specified internet network.
250 */
251struct ns_ifaddr *
252ns_iaonnetof(net)
253 union ns_net net;
254{
255 register struct ns_ifaddr *ia;
256
257#define NtoL(x) (*(long *)(&(x)))
258 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
259 if (NtoL(ia->ia_net) == NtoL(net))
260 return (ia);
261 return ((struct ns_ifaddr *)0);
262}
263#endif