⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datagram.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
字号:
  1 /*
  2  *      SUCS    NET2 Debugged.
  3  *
  4  *      Generic datagram handling routines. These are generic for all protocols. Possibly a generic IP version on top
  5  *      of these would make sense. Not tonight however 8-).
  6  *      This is used because UDP, RAW, PACKET and the to be released IPX layer all have identical select code and mostly
  7  *      identical recvfrom() code. So we share it here. The select was shared before but buried in udp.c so I moved it.
  8  *
  9  *      Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>. (datagram_select() from old udp.c code)
 10  *
 11  *      Fixes:
 12  *              Alan Cox        :       NULL return from skb_peek_copy() understood
 13  *              Alan Cox        :       Rewrote skb_read_datagram to avoid the skb_peek_copy stuff.
 14  *              Alan Cox        :       Added support for SOCK_SEQPACKET. IPX can no longer use the SO_TYPE hack but
 15  *                                      AX.25 now works right, and SPX is feasible.
 16  *              Alan Cox        :       Fixed write select of non IP protocol crash.
 17  */
 18 
 19 #include <linux/config.h>
 20 #include <linux/types.h>
 21 #include <linux/kernel.h>
 22 #include <asm/segment.h>
 23 #include <asm/system.h>
 24 #include <linux/mm.h>
 25 #include <linux/interrupt.h>
 26 #include <linux/in.h>
 27 #include <linux/errno.h>
 28 #include <linux/sched.h>
 29 #include "inet.h"
 30 #include "dev.h"
 31 #include "ip.h"
 32 #include "protocol.h"
 33 #include "arp.h"
 34 #include "route.h"
 35 #include "tcp.h"
 36 #include "udp.h"
 37 #include "skbuff.h"
 38 #include "sock.h"
 39 
 40 
 41 /*
 42  *      Get a datagram skbuff, understands the peeking, nonblocking wakeups and possible
 43  *      races. This replaces identical code in packet,raw and udp, as well as the yet to
 44  *      be released IPX support. It also finally fixes the long standing peek and read
 45  *      race for datagram sockets. If you alter this routine remember it must be
 46  *      re-entrant.
 47  */
 48 
 49 struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
 50 {
 51         struct sk_buff *skb;
 52 
 53         /* Socket is inuse - so the timer doesn't attack it */
 54 restart:
 55         sk->inuse = 1;
 56         while(sk->rqueue == NULL)       /* No data */
 57         {
 58                 /* If we are shutdown then no more data is going to appear. We are done */
 59                 if (sk->shutdown & RCV_SHUTDOWN)
 60                 {
 61                         release_sock(sk);
 62                         *err=0;
 63                         return NULL;
 64                 }
 65 
 66                 if(sk->err)
 67                 {
 68                         release_sock(sk);
 69                         *err=-sk->err;
 70                         sk->err=0;
 71                         return NULL;
 72                 }
 73 
 74                 /* Sequenced packets can come disconnected. If so we report the problem */
 75                 if(sk->type==SOCK_SEQPACKET && sk->state!=TCP_ESTABLISHED)
 76                 {
 77                         release_sock(sk);
 78                         *err=-ENOTCONN;
 79                         return NULL;
 80                 }
 81 
 82                 /* User doesn't want to wait */
 83                 if (noblock)
 84                 {
 85                         release_sock(sk);
 86                         *err=-EAGAIN;
 87                         return NULL;
 88                 }
 89                 release_sock(sk);
 90 
 91                 /* Interrupts off so that no packet arrives before we begin sleeping.
 92                    Otherwise we might miss our wake up */
 93                 cli();
 94                 if (sk->rqueue == NULL)
 95                 {
 96                         interruptible_sleep_on(sk->sleep);
 97                         /* Signals may need a restart of the syscall */
 98                         if (current->signal & ~current->blocked)
 99                         {
100                                 sti();
101                                 *err=-ERESTARTSYS;
102                                 return(NULL);
103                         }
104                         if(sk->err != 0)        /* Error while waiting for packet
105                                                    eg an icmp sent earlier by the
106                                                    peer has finaly turned up now */
107                         {
108                                 *err = -sk->err;
109                                 sti();
110                                 sk->err=0;
111                                 return NULL;
112                         }
113                 }
114                 sk->inuse = 1;
115                 sti();
116           }
117           /* Again only user level code calls this function, so nothing interrupt level
118              will suddenely eat the rqueue */
119           if (!(flags & MSG_PEEK))
120           {
121                 skb=skb_dequeue(&sk->rqueue);
122                 if(skb!=NULL)
123                         skb->users++;
124                 else
125                         goto restart;   /* Avoid race if someone beats us to the data */
126           }
127           else
128           {
129                 cli();
130                 skb=skb_peek(&sk->rqueue);
131                 if(skb!=NULL)
132                         skb->users++;
133                 sti();
134                 if(skb==NULL)   /* shouldn't happen but .. */
135                         *err=-EAGAIN;
136           }
137           return skb;
138 }
139 
140 void skb_free_datagram(struct sk_buff *skb)
141 {
142         unsigned long flags;
143 
144         save_flags(flags);
145         cli();
146         skb->users--;
147         if(skb->users>0)
148         {
149                 restore_flags(flags);
150                 return;
151         }
152         /* See if it needs destroying */
153         if(skb->list == NULL)   /* Been dequeued by someone - ie its read */
154                 kfree_skb(skb,FREE_READ);
155         restore_flags(flags);
156 }
157 
158 void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
159 {
160         /* We will know all about the fraglist options to allow >4K receives
161            but not this release */
162         memcpy_tofs(to,skb->h.raw+offset,size);
163 }
164 
165 /*
166  *      Datagram select: Again totally generic. Moved from udp.c
167  *      Now does seqpacket.
168  */
169 
170 int datagram_select(struct sock *sk, int sel_type, select_table *wait)
171 {
172         select_wait(sk->sleep, wait);
173         switch(sel_type)
174         {
175                 case SEL_IN:
176                         if (sk->type==SOCK_SEQPACKET && sk->state==TCP_CLOSE)
177                         {
178                                 /* Connection closed: Wake up */
179                                 return(1);
180                         }
181                         if (sk->rqueue != NULL || sk->err != 0)
182                         {       /* This appears to be consistent
183                                    with other stacks */
184                                 return(1);
185                         }
186                         return(0);
187 
188                 case SEL_OUT:
189                         if (sk->prot && sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
190                         {
191                                 return(1);
192                         }
193                         if (sk->prot==NULL && sk->sndbuf-sk->wmem_alloc >= MIN_WRITE_SPACE)
194                         {
195                                 return(1);
196                         }
197                         return(0);
198 
199                 case SEL_EX:
200                         if (sk->err)
201                                 return(1); /* Socket has gone into error state (eg icmp error) */
202                         return(0);
203         }
204         return(0);
205 }
206 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -