XINU
udp.c
Go to the documentation of this file.
1 /* udp.c - udp_init, udp_in, udp_register, udp_send, udp_sendto, */
2 /* udp_recv, udp_recvaddr, udp_release, udp_ntoh, udp_hton */
3 
4 #include <xinu.h>
5 
6 struct udpentry udptab[UDP_SLOTS]; /* Table of UDP endpoints */
7 
8 /*------------------------------------------------------------------------
9  * udp_init - Initialize all entries in the UDP endpoint table
10  *------------------------------------------------------------------------
11  */
12 void udp_init(void)
13 {
14 
15  int32 i; /* Index into the UDP table */
16 
17  for(i=0; i<UDP_SLOTS; i++) {
18  udptab[i].udstate = UDP_FREE;
19  }
20 
21  return;
22 }
23 
24 
25 /*------------------------------------------------------------------------
26  * udp_in - Handle an incoming UDP packet
27  *------------------------------------------------------------------------
28  */
29 void udp_in(
30  struct netpacket *pktptr /* Pointer to the packet */
31  )
32 {
33  intmask mask; /* Saved interrupt mask */
34  int32 i; /* Index into udptab */
35  struct udpentry *udptr; /* Pointer to a udptab entry */
36 
37 
38  /* Ensure only one process can access the UDP table at a time */
39 
40  mask = disable();
41 
42  for (i=0; i<UDP_SLOTS; i++) {
43  udptr = &udptab[i];
44  if (udptr->udstate == UDP_FREE) {
45  continue;
46  }
47 
48  if ((pktptr->net_udpdport == udptr->udlocport) &&
49  ((udptr->udremport == 0) ||
50  (pktptr->net_udpsport == udptr->udremport)) &&
51  ( ((udptr->udremip==0) ||
52  (pktptr->net_ipsrc == udptr->udremip))) ) {
53 
54  /* Entry matches incoming packet */
55 
56  if (udptr->udcount < UDP_QSIZ) {
57  udptr->udcount++;
58  udptr->udqueue[udptr->udtail++] = pktptr;
59  if (udptr->udtail >= UDP_QSIZ) {
60  udptr->udtail = 0;
61  }
62  if (udptr->udstate == UDP_RECV) {
63  udptr->udstate = UDP_USED;
64  send (udptr->udpid, OK);
65  }
66  restore(mask);
67  return;
68  }
69  }
70  }
71 
72  /* No match - simply discard packet */
73 
74  freebuf((char *) pktptr);
75  restore(mask);
76  return;
77 }
78 
79 /*------------------------------------------------------------------------
80  * udp_register - Register a remote IP, remote port & local port to
81  * receive incoming UDP messages from the specified
82  * remote site sent to the specified local port
83  *------------------------------------------------------------------------
84  */
86  uint32 remip, /* Remote IP address or zero */
87  uint16 remport, /* Remote UDP protocol port */
88  uint16 locport /* Local UDP protocol port */
89  )
90 {
91  intmask mask; /* Saved interrupt mask */
92  int32 slot; /* Index into udptab */
93  struct udpentry *udptr; /* Pointer to udptab entry */
94 
95  /* Ensure only one process can access the UDP table at a time */
96 
97  mask = disable();
98 
99  /* See if request already registered */
100 
101  for (slot=0; slot<UDP_SLOTS; slot++) {
102  udptr = &udptab[slot];
103  if (udptr->udstate == UDP_FREE) {
104  continue;
105  }
106 
107  /* Look at this entry in table */
108 
109  if ( (remport == udptr->udremport) &&
110  (locport == udptr->udlocport) &&
111  (remip == udptr->udremip ) ) {
112 
113  /* Request is already in the table */
114 
115  restore(mask);
116  return SYSERR;
117  }
118  }
119 
120  /* Find a free slot and allocate it */
121 
122  for (slot=0; slot<UDP_SLOTS; slot++) {
123  udptr = &udptab[slot];
124  if (udptr->udstate != UDP_FREE) {
125  continue;
126  }
127  udptr->udlocport = locport;
128  udptr->udremport = remport;
129  udptr->udremip = remip;
130  udptr->udcount = 0;
131  udptr->udhead = udptr->udtail = 0;
132  udptr->udpid = -1;
133  udptr->udstate = UDP_USED;
134  restore(mask);
135  return slot;
136  }
137 
138  restore(mask);
139  return SYSERR;
140 }
141 
142 /*------------------------------------------------------------------------
143  * udp_recv - Receive a UDP packet
144  *------------------------------------------------------------------------
145  */
147  uid32 slot, /* Slot in table to use */
148  char *buff, /* Buffer to hold UDP data */
149  int32 len, /* Length of buffer */
150  uint32 timeout /* Read timeout in msec */
151  )
152 {
153  intmask mask; /* Saved interrupt mask */
154  struct udpentry *udptr; /* Pointer to udptab entry */
155  umsg32 msg; /* Message from recvtime() */
156  struct netpacket *pkt; /* Pointer to packet being read */
157  int32 i; /* Counts bytes copied */
158  int32 msglen; /* Length of UDP data in packet */
159  char *udataptr; /* Pointer to UDP data */
160 
161  /* Ensure only one process can access the UDP table at a time */
162 
163  mask = disable();
164 
165  /* Verify that the slot is valid */
166 
167  if ((slot < 0) || (slot >= UDP_SLOTS)) {
168  restore(mask);
169  return SYSERR;
170  }
171 
172  /* Get pointer to table entry */
173 
174  udptr = &udptab[slot];
175 
176  /* Verify that the slot has been registered and is valid */
177 
178  if (udptr->udstate != UDP_USED) {
179  restore(mask);
180  return SYSERR;
181  }
182 
183  /* Wait for a packet to arrive */
184 
185  if (udptr->udcount == 0) { /* No packet is waiting */
186  udptr->udstate = UDP_RECV;
187  udptr->udpid = currpid;
188  msg = recvclr();
189  msg = recvtime(timeout); /* Wait for a packet */
190  udptr->udstate = UDP_USED;
191  if (msg == TIMEOUT) {
192  restore(mask);
193  return TIMEOUT;
194  } else if (msg != OK) {
195  restore(mask);
196  return SYSERR;
197  }
198  }
199 
200  /* Packet has arrived -- dequeue it */
201 
202  pkt = udptr->udqueue[udptr->udhead++];
203  if (udptr->udhead >= UDP_QSIZ) {
204  udptr->udhead = 0;
205  }
206  udptr->udcount--;
207 
208  /* Copy UDP data from packet into caller's buffer */
209 
210  msglen = pkt->net_udplen - UDP_HDR_LEN;
211  udataptr = (char *)pkt->net_udpdata;
212  if (len < msglen) {
213  msglen = len;
214  }
215  for (i=0; i<msglen; i++) {
216  *buff++ = *udataptr++;
217  }
218  freebuf((char *)pkt);
219  restore(mask);
220  return msglen;
221 }
222 
223 /*------------------------------------------------------------------------
224  * udp_recvaddr - Receive a UDP packet and record the sender's address
225  *------------------------------------------------------------------------
226  */
228  uid32 slot, /* Slot in table to use */
229  uint32 *remip, /* Loc for remote IP address */
230  uint16 *remport, /* Loc for remote protocol port */
231  char *buff, /* Buffer to hold UDP data */
232  int32 len, /* Length of buffer */
233  uint32 timeout /* Read timeout in msec */
234  )
235 {
236  intmask mask; /* Saved interrupt mask */
237  struct udpentry *udptr; /* Pointer to udptab entry */
238  umsg32 msg; /* Message from recvtime() */
239  struct netpacket *pkt; /* Pointer to packet being read */
240  int32 msglen; /* Length of UDP data in packet */
241  int32 i; /* Counts bytes copied */
242  char *udataptr; /* Pointer to UDP data */
243 
244  /* Ensure only one process can access the UDP table at a time */
245 
246  mask = disable();
247 
248  /* Verify that the slot is valid */
249 
250  if ((slot < 0) || (slot >= UDP_SLOTS)) {
251  restore(mask);
252  return SYSERR;
253  }
254 
255  /* Get pointer to table entry */
256 
257  udptr = &udptab[slot];
258 
259  /* Verify that the slot has been registered and is valid */
260 
261  if (udptr->udstate != UDP_USED) {
262  restore(mask);
263  return SYSERR;
264  }
265 
266  /* Wait for a packet to arrive */
267 
268  if (udptr->udcount == 0) { /* No packet is waiting */
269  udptr->udstate = UDP_RECV;
270  udptr->udpid = currpid;
271  msg = recvclr();
272  msg = recvtime(timeout); /* Wait for a packet */
273  udptr->udstate = UDP_USED;
274  if (msg == TIMEOUT) {
275  restore(mask);
276  return TIMEOUT;
277  } else if (msg != OK) {
278  restore(mask);
279  return SYSERR;
280  }
281  }
282 
283  /* Packet has arrived -- dequeue it */
284 
285  pkt = udptr->udqueue[udptr->udhead++];
286  if (udptr->udhead >= UDP_QSIZ) {
287  udptr->udhead = 0;
288  }
289 
290  /* Record sender's IP address and UDP port number */
291 
292  *remip = pkt->net_ipsrc;
293  *remport = pkt->net_udpsport;
294 
295  udptr->udcount--;
296 
297  /* Copy UDP data from packet into caller's buffer */
298 
299  msglen = pkt->net_udplen - UDP_HDR_LEN;
300  udataptr = (char *)pkt->net_udpdata;
301  if (len < msglen) {
302  msglen = len;
303  }
304  for (i=0; i<msglen; i++) {
305  *buff++ = *udataptr++;
306  }
307  freebuf((char *)pkt);
308  restore(mask);
309  return msglen;
310 }
311 
312 /*------------------------------------------------------------------------
313  * udp_send - Send a UDP packet using info in a UDP table entry
314  *------------------------------------------------------------------------
315  */
317  uid32 slot, /* Table slot to use */
318  char *buff, /* Buffer of UDP data */
319  int32 len /* Length of data in buffer */
320  )
321 {
322  intmask mask; /* Saved interrupt mask */
323  struct netpacket *pkt; /* Pointer to packet buffer */
324  int32 pktlen; /* Total packet length */
325  static uint16 ident = 1; /* Datagram IDENT field */
326  char *udataptr; /* Pointer to UDP data */
327  uint32 remip; /* Remote IP address to use */
328  uint16 remport; /* Remote protocol port to use */
329  uint16 locport; /* Local protocol port to use */
330  uint32 locip; /* Local IP address taken from */
331  /* the interface */
332  struct udpentry *udptr; /* Pointer to table entry */
333 
334  /* Ensure only one process can access the UDP table at a time */
335 
336  mask = disable();
337 
338  /* Verify that the slot is valid */
339 
340  if ( (slot < 0) || (slot >= UDP_SLOTS) ) {
341  restore(mask);
342  return SYSERR;
343  }
344 
345  /* Get pointer to table entry */
346 
347  udptr = &udptab[slot];
348 
349  /* Verify that the slot has been registered and is valid */
350 
351  if (udptr->udstate == UDP_FREE) {
352  restore(mask);
353  return SYSERR;
354  }
355 
356  /* Verify that the slot has a specified remote address */
357 
358  remip = udptr->udremip;
359  if (remip == 0) {
360  restore(mask);
361  return SYSERR;
362  }
363 
364  locip = NetData.ipucast;
365  remport = udptr->udremport;
366  locport = udptr->udlocport;
367 
368  /* Allocate a network buffer to hold the packet */
369 
370  pkt = (struct netpacket *)getbuf(netbufpool);
371 
372  if ((int32)pkt == SYSERR) {
373  restore(mask);
374  return SYSERR;
375  }
376 
377  /* Compute packet length as UDP data size + fixed header size */
378 
379  pktlen = ((char *)&pkt->net_udpdata - (char *)pkt) + len;
380 
381  /* Create a UDP packet in pkt */
382 
384  pkt->net_ethtype = 0x0800; /* Type is IP */
385  pkt->net_ipvh = 0x45; /* IP version and hdr length */
386  pkt->net_iptos = 0x00; /* Type of service */
387  pkt->net_iplen= pktlen - ETH_HDR_LEN;/* Total IP datagram length*/
388  pkt->net_ipid = ident++; /* Datagram gets next IDENT */
389  pkt->net_ipfrag = 0x0000; /* IP flags & fragment offset */
390  pkt->net_ipttl = 0xff; /* IP time-to-live */
391  pkt->net_ipproto = IP_UDP; /* Datagram carries UDP */
392  pkt->net_ipcksum = 0x0000; /* initial checksum */
393  pkt->net_ipsrc = locip; /* IP source address */
394  pkt->net_ipdst = remip; /* IP destination address */
395 
396  pkt->net_udpsport = locport; /* Local UDP protocol port */
397  pkt->net_udpdport = remport; /* Remote UDP protocol port */
398  pkt->net_udplen = (uint16)(UDP_HDR_LEN+len); /* UDP length */
399  pkt->net_udpcksum = 0x0000; /* Ignore UDP checksum */
400  udataptr = (char *) pkt->net_udpdata;
401  for (; len>0; len--) {
402  *udataptr++ = *buff++;
403  }
404 
405  /* Call ipsend to send the datagram */
406 
407  ip_send(pkt);
408  restore(mask);
409  return OK;
410 }
411 
412 
413 /*------------------------------------------------------------------------
414  * udp_sendto - Send a UDP packet to a specified destination
415  *------------------------------------------------------------------------
416  */
418  uid32 slot, /* UDP table slot to use */
419  uint32 remip, /* Remote IP address to use */
420  uint16 remport, /* Remote protocol port to use */
421  char *buff, /* Buffer of UDP data */
422  int32 len /* Length of data in buffer */
423  )
424 {
425  intmask mask; /* Saved interrupt mask */
426  struct netpacket *pkt; /* Pointer to a packet buffer */
427  int32 pktlen; /* Total packet length */
428  static uint16 ident = 1; /* Datagram IDENT field */
429  struct udpentry *udptr; /* Pointer to a UDP table entry */
430  char *udataptr; /* Pointer to UDP data */
431 
432  /* Ensure only one process can access the UDP table at a time */
433 
434  mask = disable();
435 
436  /* Verify that the slot is valid */
437 
438  if ( (slot < 0) || (slot >= UDP_SLOTS) ) {
439  restore(mask);
440  return SYSERR;
441  }
442 
443  /* Get pointer to table entry */
444 
445  udptr = &udptab[slot];
446 
447  /* Verify that the slot has been registered and is valid */
448 
449  if (udptr->udstate == UDP_FREE) {
450  restore(mask);
451  return SYSERR;
452  }
453 
454  /* Allocate a network buffer to hold the packet */
455 
456  pkt = (struct netpacket *)getbuf(netbufpool);
457 
458  if ((int32)pkt == SYSERR) {
459  restore(mask);
460  return SYSERR;
461  }
462 
463  /* Compute packet length as UDP data size + fixed header size */
464 
465  pktlen = ((char *)&pkt->net_udpdata - (char *)pkt) + len;
466 
467  /* Create UDP packet in pkt */
468 
470  pkt->net_ethtype = 0x0800; /* Type is IP */
471  pkt->net_ipvh = 0x45; /* IP version and hdr length */
472  pkt->net_iptos = 0x00; /* Type of service */
473  pkt->net_iplen= pktlen - ETH_HDR_LEN;/* total IP datagram length*/
474  pkt->net_ipid = ident++; /* Datagram gets next IDENT */
475  pkt->net_ipfrag = 0x0000; /* IP flags & fragment offset */
476  pkt->net_ipttl = 0xff; /* IP time-to-live */
477  pkt->net_ipproto = IP_UDP; /* Datagram carries UDP */
478  pkt->net_ipcksum = 0x0000; /* Initial checksum */
479  pkt->net_ipsrc = NetData.ipucast;/* IP source address */
480  pkt->net_ipdst = remip; /* IP destination address */
481  pkt->net_udpsport = udptr->udlocport;/* local UDP protocol port */
482  pkt->net_udpdport = remport; /* Remote UDP protocol port */
483  pkt->net_udplen = (uint16)(UDP_HDR_LEN+len); /* UDP length */
484  pkt->net_udpcksum = 0x0000; /* Ignore UDP checksum */
485  udataptr = (char *) pkt->net_udpdata;
486  for (; len>0; len--) {
487  *udataptr++ = *buff++;
488  }
489 
490  /* Call ipsend to send the datagram */
491 
492  ip_send(pkt);
493  restore(mask);
494  return OK;
495 }
496 
497 
498 /*------------------------------------------------------------------------
499  * udp_release - Release a previously-registered UDP slot
500  *------------------------------------------------------------------------
501  */
503  uid32 slot /* Table slot to release */
504  )
505 {
506  intmask mask; /* Saved interrupt mask */
507  struct udpentry *udptr; /* Pointer to udptab entry */
508  struct netpacket *pkt; /* pointer to packet being read */
509 
510  /* Ensure only one process can access the UDP table at a time */
511 
512  mask = disable();
513 
514  /* Verify that the slot is valid */
515 
516  if ( (slot < 0) || (slot >= UDP_SLOTS) ) {
517  restore(mask);
518  return SYSERR;
519  }
520 
521  /* Get pointer to table entry */
522 
523  udptr = &udptab[slot];
524 
525  /* Verify that the slot has been registered and is valid */
526 
527  if (udptr->udstate == UDP_FREE) {
528  restore(mask);
529  return SYSERR;
530  }
531 
532  /* Defer rescheduling to prevent freebuf from switching context */
533 
535  while (udptr->udcount > 0) {
536  pkt = udptr->udqueue[udptr->udhead++];
537  if (udptr->udhead >= UDP_QSIZ) {
538  udptr->udhead = 0;
539  }
540  freebuf((char *)pkt);
541  udptr->udcount--;
542  }
543  udptr->udstate = UDP_FREE;
545  restore(mask);
546  return OK;
547 }
548 
549 /*------------------------------------------------------------------------
550  * udp_ntoh - Convert UDP header fields from net to host byte order
551  *------------------------------------------------------------------------
552  */
553 void udp_ntoh(
554  struct netpacket *pktptr
555  )
556 {
557  pktptr->net_udpsport = ntohs(pktptr->net_udpsport);
558  pktptr->net_udpdport = ntohs(pktptr->net_udpdport);
559  pktptr->net_udplen = ntohs(pktptr->net_udplen);
560  return;
561 }
562 
563 /*------------------------------------------------------------------------
564  * udp_hton - Convert packet header fields from host to net byte order
565  *------------------------------------------------------------------------
566  */
567 void udp_hton(
568  struct netpacket *pktptr
569  )
570 {
571  pktptr->net_udpsport = htons(pktptr->net_udpsport);
572  pktptr->net_udpdport = htons(pktptr->net_udpdport);
573  pktptr->net_udplen = htons(pktptr->net_udplen);
574  return;
575 }
#define IP_UDP
IP向けのUDPプロトコルタイプ
Definition: ip.h:16
uint16 net_udpcksum
Definition: net.h:35
uint32 ipucast
Definition: net.h:55
pid32 currpid
現在実行中のプロセス。
Definition: initialize.c:32
uint16 udremport
Definition: udp.h:24
uint16 net_ethtype
Definition: net.h:19
void restore(intmask)
int32 udhead
Definition: udp.h:26
struct netpacket * udqueue[UDP_QSIZ]
Definition: udp.h:30
if(!(yy_init))
Definition: lex.yy.c:679
struct network NetData
Definition: net.c:6
全てのシステムヘッダファイルをインクルードする。
#define SYSERR
処理が失敗した場合
Definition: kernel.h:79
#define UDP_USED
Definition: udp.h:12
uint32 udremip
Definition: udp.h:22
uint16 net_ipid
Definition: net.h:23
int32 udcount
Definition: udp.h:28
int32 udtail
Definition: udp.h:27
void udp_ntoh(struct netpacket *pktptr)
Definition: udp.c:553
uid32 udp_register(uint32 remip, uint16 remport, uint16 locport)
Definition: udp.c:85
uint16 net_ipfrag
Definition: net.h:24
#define UDP_RECV
Definition: udp.h:13
uint16 net_udpsport
Definition: net.h:32
#define OK
処理が成功した場合
Definition: kernel.h:77
#define UDP_SLOTS
Definition: udp.h:3
syscall send(pid32, umsg32)
プロセスにメッセージを送信し、受信側が待機状態の場合はREADY状態にする。
Definition: send.c:21
byte net_ethsrc[ETH_ADDR_LEN]
Definition: net.h:18
int32 udp_recvaddr(uid32 slot, uint32 *remip, uint16 *remport, char *buff, int32 len, uint32 timeout)
Definition: udp.c:227
uint16 net_iplen
Definition: net.h:22
#define TIMEOUT
システムコールがタイムアウトした場合
Definition: kernel.h:83
int32 status
ステータスを意味する返り値の型(OK/SYSERR)
Definition: kernel.h:57
pid32 udpid
Definition: udp.h:29
uint32 umsg32
プロセス間で渡されるメッセージ
Definition: kernel.h:32
status resched_cntl(int32)
再スケジューリングを延期させるか、もしくは許可させるかを制御する。
Definition: resched.c:81
status udp_send(uid32 slot, char *buff, int32 len)
Definition: udp.c:316
struct udpentry udptab[UDP_SLOTS]
Definition: udp.c:6
byte ethucast[ETH_ADDR_LEN]
Definition: net.h:64
void udp_in(struct netpacket *pktptr)
Definition: udp.c:29
Definition: udp.h:20
#define UDP_QSIZ
Definition: udp.h:4
umsg32 recvclr(void)
受信メッセージをクリアし、待機している場合はメッセージを返す。
Definition: recvclr.c:14
int32 udp_recv(uid32 slot, char *buff, int32 len, uint32 timeout)
Definition: udp.c:146
#define DEFER_STOP
遅延リスケジューリングの停止
Definition: resched.h:10
uint16 net_udplen
Definition: net.h:34
uint32 intmask
保存された割り込みマスク
Definition: kernel.h:38
#define DEFER_START
遅延リスケジューリングの開始
Definition: resched.h:8
int int32
符号あり32ビット整数(int)
Definition: kernel.h:11
uint16 udlocport
Definition: udp.h:25
uint16 net_ipcksum
Definition: net.h:27
byte net_udpdata[1500-28]
Definition: net.h:36
bpid32 netbufpool
Definition: net.c:7
unsigned short uint16
符号なし16ビット整数(unsigned short)
Definition: kernel.h:17
#define ntohs(x)
Definition: prototypes.h:622
status udp_release(uid32 slot)
Definition: udp.c:502
char * getbuf(bpid32)
事前に確保されたバッファプールからバッファを取得する。
Definition: getbuf.c:19
int32 udstate
Definition: udp.h:21
#define ETH_HDR_LEN
Definition: ether.h:22
byte net_iptos
Definition: net.h:21
Definition: net.h:16
byte net_ipvh
Definition: net.h:20
uint32 net_ipsrc
Definition: net.h:28
uint32 net_ipdst
Definition: net.h:29
status udp_sendto(uid32 slot, uint32 remip, uint16 remport, char *buff, int32 len)
Definition: udp.c:417
uint16 net_udpdport
Definition: net.h:33
syscall freebuf(char *)
バッファプールから取得したバッファを解放する。
Definition: freebuf.c:19
status ip_send(struct netpacket *)
Definition: ip.c:103
#define ETH_ADDR_LEN
Definition: ether.h:10
byte net_ipproto
Definition: net.h:26
void udp_init(void)
Definition: udp.c:12
byte net_ipttl
Definition: net.h:25
umsg32 recvtime(int32)
Definition: recvtime.c:17
unsigned int uint32
符号なし32ビット整数(unsigned int)
Definition: kernel.h:15
#define htons(x)
Definition: prototypes.h:619
void udp_hton(struct netpacket *pktptr)
Definition: udp.c:567
int32 uid32
UDPテーブルディスクリプタのID.
Definition: kernel.h:44
void * memcpy(void *, const void *, int32)
メモリAの領域(source)からメモリBの領域(Destination)にN Byteコピーする。
Definition: memcpy.c:13
#define UDP_HDR_LEN
Definition: udp.h:18
#define UDP_FREE
Definition: udp.h:11
intmask disable(void)
割り込み禁止(intr.Sに定義がある)