fixes for range locking
[unix-history] / usr / src / sys / deprecated / bbnnet / rdp_input.c
CommitLineData
17efd7fe
MK
1/*
2 $Log: rdp_input.c,v $
3 * Revision 2.10 85/06/18 14:37:38 walsh
4 * check for version mismatch.
5 *
6 * Revision 2.9 85/04/08 14:35:11 root
7 * *** empty log message ***
8 *
9 * Revision 2.8 85/02/26 08:26:48 walsh
10 * First pass at using IP source routing information to establish connections
11 * (possibly with hosts not known by the Internet gateways.) The hooks with
12 * TCP could be better done - particularly dealing with IP addresses in the
13 * header for checksums and tcpdb lookups.
14 *
15 * Revision 2.7 84/11/15 09:55:52 walsh
16 * redid how we deal with compiler padding in the RDP header structure.
17 *
18 * Revision 2.6 84/11/08 16:11:17 walsh
19 * Added code to gather statistics on RDP traffic. This makes the RDPCB
20 * too big unles you make mbufs 512 bytes large. RDP_CS should be turned off
21 * unless you do.
22 *
23 * Revision 2.5 84/11/06 14:30:09 walsh
24 * intorduced RDP_HLSHIFT
25 *
26 * Revision 2.4 84/11/05 16:33:07 walsh
27 * fix coding error.
28 *
29 * Revision 2.3 84/11/05 10:51:53 walsh
30 * flush debugging log if new state is RDP_sCLOSED so that packet printer/
31 * system analyst sees final transitions.
32 *
33 * Revision 2.2 84/11/02 15:28:19 walsh
34 * Allow for RDP header fields not on natural boundries. (Protocol
35 * specifiers say will be part of next version in 6-12 months).
36 * Until then, there goes the speed... Yucho modifications.
37 *
38 * Revision 2.1 84/11/02 10:12:58 walsh
39 * Fixed to include RCS comments in checked out source.
40 *
41 *
42 * description:
43 * Packet input processing for Reliable Datagram Protocol.
44 *
45 * revision 1.6
46 * date: 84/07/19 10:21:22; author: walsh; state: Exp; lines added/del: 2/1
47 * Organized macros and classified their definitions in rdp_macros.h.
48 *
49 * revision 1.5
50 * date: 84/07/10 09:59:38; author: walsh; state: Exp; lines added/del: 10/10
51 * declared some register variables.
52 *
53 * revision 1.4
54 * date: 84/07/06 14:43:19; author: wjacobso; state: Exp; lines added/del: 2/2
55 * *** empty log message ***
56 *
57 * revision 1.3
58 * date: 84/07/06 13:50:26; author: wjacobso; state: Exp; lines added/del: 6/3
59 * use RDP_ACTION macro instead of rdp_action
60 *
61 * revision 1.2
62 * date: 84/07/06 09:49:20; author: root; state: Exp; lines added/del: 27/45
63 * This version seems to run bug-free.
64 *
65 * revision 1.1
66 * date: 84/06/26 14:17:19; author: walsh; state: Exp;
67 * Initial revision
68 */
69
70
71#ifdef RDP
72#ifdef RCSIDENT
73static char rcsident[] = "$Header: rdp_input.c,v 2.10 85/06/18 14:37:38 walsh Exp $";
74#endif
75
76#include "../h/param.h"
77#include "../h/dir.h"
78#include "../h/user.h"
79#include "../h/kernel.h"
80#include "../h/inode.h"
81#include "../h/mbuf.h"
82#include "../h/socket.h"
83#include "../h/socketvar.h"
84#include "../h/syslog.h"
85
86#include "../net/if.h"
87#include "../net/route.h"
88
89#include "../bbnnet/in.h"
90#include "../bbnnet/in_var.h"
91#include "../bbnnet/net.h"
92#include "../bbnnet/in_pcb.h"
93#include "../bbnnet/ip.h"
94#include "../bbnnet/nopcb.h"
95#include "../bbnnet/rdp.h"
96#include "../bbnnet/rdp_macros.h"
97#ifdef HMP
98#include "../bbnnet/hmp_traps.h"
99#endif
100
101extern int nosum;
102
103/*
104 * this is called from ip_input() upon reception of an RDP packet.
105 */
106rdp_input(mp)
107register struct mbuf *mp;
108{
109 register RDPHDR *pkt;
110 register struct ip *ip;
111 rdpchecksum pktcksum;
112 rdpchecksum cksum;
113 register int hlen;
114 register struct inpcb *inp;
115
116 rdpstat.r_total++;
117
118 /*
119 * see ip_input(). Get access to constant part of RDP header.
120 */
121#define SZ (RDPHDRSZ + sizeof(struct ip))
122 if ((mp->m_off > MMAXOFF) || (mp->m_len < SZ))
123 {
124 if ((mp = m_pullup(mp, SZ)) == NULL)
125 {
126 rdpstat.r_tooshort ++;
127 return;
128 }
129 }
130#undef SZ
131
132 ip = mtod(mp, struct ip *);
133 pkt = (RDPHDR *) (ip + 1);
134
135 /* make sure header, incl. option region, does not overflow mbuf */
136
137 hlen = hdrlen(pkt) + sizeof(struct ip);
138 if (hlen > mp->m_len)
139 {
140 if ((mp = m_pullup(mp, hlen)) == NULL)
141 {
142 ip_log(ip, "rdp header overflow");
143#ifdef HMPTRAPS
144 /* hmp_trap(T_TCP_OVFLO, (caddr_t)0,0); */
145#else
146 /* netlog(mp); */
147#endif
148 return;
149 }
150 ip = mtod(mp, struct ip *);
151 pkt = (RDPHDR *) (ip + 1);
152 }
153
154 if (pkt->rh_ver != RDP_VERSION)
155 {
156 ip_log (ip, "rdp version mismatch");
157 netlog (mp);
158 return;
159 }
160
161 /*
162 * do checksum calculation, drop packet if bad
163 * Checksum must be done on header in net form due to byte ordering
164 * and rotations.
165 */
166
167 pktcksum = RDP_CKSUM(pkt);
168 RDP_CKSUM(pkt) = 0;
169 cksum = rdp_cksum(mp);
170 if (cksum != pktcksum)
171 {
172 rdpstat.r_badsum++;
173 if (! nosum)
174 {
175 inet_cksum_err ("rdp", ip, (u_long) pktcksum, (u_long) cksum);
176 netlog(mp);
177 return;
178 }
179 }
180
181 /* byte swap header */
182
183 pkt->rh_dlen = ntohs(pkt->rh_dlen);
184 RDP_SEQNO(pkt) = ntohl(RDP_SEQNO(pkt));
185 RDP_ACKNO(pkt) = ntohl(RDP_ACKNO(pkt));
186
187 if (ip->ip_len != hdrlen(pkt) + pkt->rh_dlen)
188 {
189 ip_log(ip, "rdp length error");
8902c2d0 190 log(LOG_INFO, "%d + %d != %d\n", hdrlen(pkt), pkt->rh_dlen,
17efd7fe
MK
191 ip->ip_len);
192 netlog(mp);
193 return;
194 }
195
196 inp = in_pcblookup(&rdp, ip->ip_src.s_addr, (u_short)pkt->rh_sport,
197 ip->ip_dst.s_addr, (u_short)pkt->rh_dport, TRUE);
198 if (inp == NULL)
199 {
200 /* nobody wants it */
201 rdpstat.r_drops ++;
202 rdp_uncon_rst (pkt);
203 }
204 else
205 {
206 register rdpstate newstate;
207 register RDPCB *rdpcb;
208
209 rdpcb = (RDPCB *)inp->inp_ppcb;
210
211#ifdef RDP_CS
212 rdpcb->r_rcvd.r_total ++;
213 if (pkt->rh_flags & (RDP_fNULL|RDP_fRST|RDP_fSYN))
214 {
215 if (pkt->rh_flags & RDP_fNULL)
216 rdpcb->r_rcvd.r_nullpkts ++;
217 if (pkt->rh_flags & RDP_fRST)
218 rdpcb->r_rcvd.r_rstpkts ++;
219 if (pkt->rh_flags & RDP_fSYN)
220 rdpcb->r_rcvd.r_synpkts ++;
221 }
222#endif
223 /* found a protocol control block for the message */
224 RDP_ACTION(RDP_iNETR, rdpcb, ((int) pkt), newstate);
225 }
226}
227
228
229/*
230 * Call a subroutine specifically tailored to deal with this state
231 * transition.
232 */
233rdpaction (input, rdpcb, arg)
234register RDPCB *rdpcb;
235{
236 register rdpstate newstate;
237
238 RDP_ACTION (input, rdpcb, arg, newstate)
239}
240
241rdp_uncon_rst (pkt)
242register RDPHDR *pkt;
243{
244 register struct ip *ip;
245 register struct mbuf *mp;
246 struct in_addr tempinaddr;
247 rdpportnum tempport;
248 long his_seqno;
249 int error;
250
251 mp = dtom(pkt);
252
253 /* make sure we don't send a RST in response to an RST */
254
255 if (pkt->rh_flags & RDP_fRST)
256 {
257 m_freem(mp);
258 return;
259 }
260 ip = (struct ip *) (((caddr_t) pkt) - sizeof(struct ip));
261
262 /* free everything but the header */
263
264 m_freem(mp->m_next);
265 mp->m_next = NULL;
266 mp->m_len = sizeof(struct ip) + RDPHDRSZ;
267
268 /* direct the packet back to the originator */
269
270 tempinaddr = ip->ip_dst;
271 ip->ip_dst = ip->ip_src;
272 ip->ip_src = tempinaddr;
273
274 tempport = pkt->rh_sport;
275 pkt->rh_sport = pkt->rh_dport;
276 pkt->rh_dport = tempport;
277
278 /*
279 * and initialize (seqno, ackno, flags) so that it's "in window"
280 * and resets him independent of his state (is acceptable to all
281 * net reception subroutines.)
282 */
283 his_seqno = RDP_SEQNO(pkt);
284 RDP_SEQNO(pkt) = htonl(RDP_ACKNO(pkt) + 1);
285 RDP_ACKNO(pkt) = htonl(his_seqno);
286 if (pkt->rh_flags & RDP_fSYN)
287 pkt->rh_flags = RDP_fRST|RDP_fACK;
288 else
289 pkt->rh_flags = RDP_fRST;
290
291 /* and send it */
292
293 pkt->rh_hdrlen = RDPHDRSZ >> RDP_HLSHIFT;
294 pkt->rh_dlen = 0;
295 RDP_CKSUM(pkt) = 0;
296
297 RDP_CKSUM(pkt) = rdp_cksum(mp);
298
299 NOPCB_IPSEND (mp, RDPHDRSZ, FALSE, error);
300#ifdef lint
301 error = error;
302#endif
303}
304
305struct mbuf *rdpdebuf;
306#ifdef RDPDEBUG
307int rdprint;
308#endif
309
310/*
311 * Write a record in the rdp debugging log
312 */
313rdp_debug(rdpcb, arg, input, newstate)
314register RDPCB *rdpcb;
315rdpstate newstate;
316{
317 register struct r_debug *dp;
318 register struct mbuf *m;
319
320#ifdef RDPDEBUG
321 if (rdprint)
322 {
323 /*
324 * Print debugging info directly on the console (use this for
325 * intial testing only).
326 */
327 printf("RDP(0x%x) %s X %s", rdpcb, rdpstates[rdpcb->r_state],
328 (input < 0 ? "send pkt" : rdpinputs[input]) );
329
330 if (input == RDP_iTIMER)
331 printf("(%s)", rdptimers[arg]);
332
333 printf(" --> %s\n",
334 rdpstates[newstate==RDP_sSAME ? rdpcb->r_state : newstate];
335 }
336#endif
337
338 /*
339 * Get an mbuf to write the debugging record into. If we don't already
340 * have one, allocate a new one.
341 */
342 if ((m = rdpdebuf) == NULL)
343 {
344 register struct mbuf *c;
345
346 if ((rdpdebuf = m = m_get(M_DONTWAIT, MT_DATA)) == NULL)
347 return;
348 /*
349 * If possible, use a cluster so that we need to wake up the
350 * raw listener less often and reduce likelihood he misses
351 * some information.
352 */
353 MCLGET(c, 1);
354 if (c)
355 {
356 m->m_off = ((int) c) - ((int) m);
357 m->m_act = (struct mbuf *) RCDBLEN;
358 }
359 else
360 m->m_act = (struct mbuf *) RDBLEN;
361 m->m_len = 0;
362 }
363
364 dp = (R_DEBUG *) (mtod(m, char *) + m->m_len);
365 /*
366 * Set up the debugging record.
367 */
368 dp->rd_iptime = iptime();
369 dp->rd_input = input;
370 dp->rd_newstate = newstate;
371 dp->rd_rdpcb = (*rdpcb); /* structure copy */
372
373 /*
374 * input == RDP_iNETR incoming packet
375 * == -1 monitor outgoing packet. Not a true
376 * transition CAUSING event, but useful.
377 */
378 if ((input == RDP_iNETR) || (input < 0))
379 {
380 register struct ip *ip;
381 register RDPHDR *pkt;
382
383 ip = (struct ip *) arg;
384 pkt = (RDPHDR *) (ip + 1);
385 dp->rd_iphdr = (*ip); /* structure copy */
386 dp->rd_rdphdr = (*pkt); /* structure copy */
387 }
388 else if (input == RDP_iTIMER)
389 dp->rd_timer = arg;
390
391 /*
392 * If the mbuf is full, dispatch it to a raw listener.
393 * Also for transition to closed state so oberver sees all and
394 * can debug stuff more easily.
395 */
396 m->m_len += sizeof(struct r_debug);
397 if ((m->m_len >= ((int) m->m_act)) || (newstate == RDP_sCLOSED))
398 {
399 m->m_act = 0;
400 rdpdebuglog(m);
401 rdpdebuf = NULL;
402 }
403}
404#endif