Add copyright
[unix-history] / usr / src / sys / netns / ns.c
CommitLineData
de9bc7de
KS
1/* ns.c 6.1 85/05/30 */
2
3#include "param.h"
4#include "mbuf.h"
5#include "ioctl.h"
6#include "protosw.h"
7#include "socket.h"
8#include "socketvar.h"
9#include "uio.h"
10#include "dir.h"
11#include "user.h"
12
13
14#include "../net/if.h"
15#include "../net/route.h"
16#include "../net/af.h"
17
18#include "ns.h"
19#include "ns_if.h"
20
21#ifdef NS
22
23struct ns_ifaddr *ns_ifaddr;
24
25ns_hash(sns, hp)
26 register struct sockaddr_ns *sns;
27 struct afhash *hp;
28{
29 register long hash = 0;
30 register u_short *s = sns->sns_addr.x_host.s_host;
31
32 hp->afh_nethash = ns_netof(sns->sns_addr);
33 hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
34 hp->afh_hosthash = hash;
35}
36
37
38ns_netmatch(sns1, sns2)
39 struct sockaddr_ns *sns1, *sns2;
40{
41
42 return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr));
43}
44
45/*
46 * Generic internet control operations (ioctl's).
47 */
48ns_control(so, cmd, data, ifp)
49 struct socket *so;
50 int cmd;
51 caddr_t data;
52 register struct ifnet *ifp;
53{
54 register struct ifreq *ifr = (struct ifreq *)data;
55 register struct ns_ifaddr *ia;
56 struct ifaddr *ifa;
57 struct mbuf *m;
58 int error;
59
60 if (!suser())
61 return (u.u_error);
62
63 /*
64 * Find address for this interface, if it exists.
65 */
66 for (ia = ns_ifaddr; ia; ia = ia->ia_next)
67 if (ia->ia_ifp == ifp)
68 break;
69
70 switch (cmd) {
71
72 case SIOCGIFADDR:
73 case SIOCGIFBRDADDR:
74 case SIOCGIFDSTADDR:
75 if (ia == (struct ns_ifaddr *)0)
76 return (EADDRNOTAVAIL);
77 break;
78
79 case SIOCSIFDSTADDR:
80 return (EOPNOTSUPP);
81
82 case SIOCSIFADDR:
83 if (ia == (struct ns_ifaddr *)0) {
84 m = m_getclr(M_WAIT, MT_IFADDR);
85 if (m == (struct mbuf *)NULL)
86 return (ENOBUFS);
87 if (ia = ns_ifaddr) {
88 for ( ; ia->ia_next; ia = ia->ia_next)
89 ;
90 ia->ia_next = mtod(m, struct ns_ifaddr *);
91 } else
92 ns_ifaddr = mtod(m, struct ns_ifaddr *);
93 ia = mtod(m, struct ns_ifaddr *);
94 if (ifa = ifp->if_addrlist) {
95 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
96 ;
97 ifa->ifa_next = (struct ifaddr *) ia;
98 } else
99 ifp->if_addrlist = (struct ifaddr *) ia;
100 ia->ia_ifp = ifp;
101 IA_SNS(ia)->sns_family = AF_NS;
102 }
103 break;
104 }
105
106 switch (cmd) {
107
108 case SIOCGIFADDR:
109 ifr->ifr_addr = ia->ia_addr;
110 break;
111
112 case SIOCGIFBRDADDR:
113 if (ia == (struct ns_ifaddr *)0)
114 return (EADDRNOTAVAIL);
115 if ((ifp->if_flags & IFF_BROADCAST) == 0)
116 return (EINVAL);
117 ifr->ifr_dstaddr = ia->ia_broadaddr;
118 break;
119
120 case SIOCGIFDSTADDR:
121 if (ia == (struct ns_ifaddr *)0)
122 return (EADDRNOTAVAIL);
123 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
124 return (EINVAL);
125 ifr->ifr_dstaddr = ia->ia_dstaddr;
126 break;
127
128 case SIOCSIFADDR:
129 return
130 (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr));
131
132 default:
133 if (ifp->if_ioctl == 0)
134 return (EOPNOTSUPP);
135 return ((*ifp->if_ioctl)(ifp, cmd, data));
136 }
137 return (0);
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