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

📄 sock.c

📁 An implementation of the TCP/IP protocol suite for the LINUX operating system. INET is implemented u
💻 C
📖 第 1 页 / 共 5 页
字号:
  1 /*
  2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
  3  *              operating system.  INET is implemented using the  BSD Socket
  4  *              interface as the means of communication with the user level.
  5  *
  6  *              SOCK - AF_INET protocol family socket handler.
  7  *
  8  * Version:     @(#)sock.c      1.0.17  06/02/93
  9  *
 10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
 11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 12  *              Florian La Roche, <flla@stud.uni-sb.de>
 13  *
 14  * Fixes:
 15  *              Alan Cox        :       Numerous verify_area() problems
 16  *              Alan Cox        :       Connecting on a connecting socket
 17  *                                      now returns an error for tcp.
 18  *              Alan Cox        :       sock->protocol is set correctly.
 19  *                                      and is not sometimes left as 0.
 20  *              Alan Cox        :       connect handles icmp errors on a
 21  *                                      connect properly. Unfortunately there
 22  *                                      is a restart syscall nasty there. I
 23  *                                      can't match BSD without hacking the C
 24  *                                      library. Ideas urgently sought!
 25  *              Alan Cox        :       Disallow bind() to addresses that are
 26  *                                      not ours - especially broadcast ones!!
 27  *              Alan Cox        :       Socket 1024 _IS_ ok for users. (fencepost)
 28  *              Alan Cox        :       sock_wfree/sock_rfree don't destroy sockets,
 29  *                                      instead they leave that for the DESTROY timer.
 30  *              Alan Cox        :       Clean up error flag in accept
 31  *              Alan Cox        :       TCP ack handling is buggy, the DESTROY timer
 32  *                                      was buggy. Put a remove_sock() in the handler
 33  *                                      for memory when we hit 0. Also altered the timer
 34  *                                      code. The ACK stuff can wait and needs major 
 35  *                                      TCP layer surgery.
 36  *              Alan Cox        :       Fixed TCP ack bug, removed remove sock
 37  *                                      and fixed timer/inet_bh race.
 38  *              Alan Cox        :       Added zapped flag for TCP
 39  *              Alan Cox        :       Move kfree_skb into skbuff.c and tidied up surplus code
 40  *              Alan Cox        :       for new sk_buff allocations wmalloc/rmalloc now call alloc_skb
 41  *              Alan Cox        :       kfree_s calls now are kfree_skbmem so we can track skb resources
 42  *              Alan Cox        :       Supports socket option broadcast now as does udp. Packet and raw need fixing.
 43  *              Alan Cox        :       Added RCVBUF,SNDBUF size setting. It suddenely occured to me how easy it was so...
 44  *              Rick Sladkey    :       Relaxed UDP rules for matching packets.
 45  *              C.E.Hawkins     :       IFF_PROMISC/SIOCGHWADDR support
 46  *      Pauline Middelink       :       Pidentd support
 47  *              Alan Cox        :       Fixed connect() taking signals I think.
 48  *              Alan Cox        :       SO_LINGER supported
 49  *              Alan Cox        :       Error reporting fixes
 50  *              Anonymous       :       inet_create tidied up (sk->reuse setting)
 51  *              Alan Cox        :       inet sockets don't set sk->type!
 52  *              Alan Cox        :       Split socket option code
 53  *              Alan Cox        :       Callbacks
 54  *              Alan Cox        :       Nagle flag for Charles & Johannes stuff
 55  *
 56  * To Fix:
 57  *
 58  *
 59  *              This program is free software; you can redistribute it and/or
 60  *              modify it under the terms of the GNU General Public License
 61  *              as published by the Free Software Foundation; either version
 62  *              2 of the License, or (at your option) any later version.
 63  */
 64 
 65 #include <linux/config.h>
 66 #include <linux/errno.h>
 67 #include <linux/types.h>
 68 #include <linux/socket.h>
 69 #include <linux/in.h>
 70 #include <linux/kernel.h>
 71 #include <linux/major.h>
 72 #include <linux/sched.h>
 73 #include <linux/timer.h>
 74 #include <linux/string.h>
 75 #include <linux/sockios.h>
 76 #include <linux/net.h>
 77 #include <linux/fcntl.h>
 78 #include <linux/mm.h>
 79 #include <linux/interrupt.h>
 80 
 81 #include <asm/segment.h>
 82 #include <asm/system.h>
 83 
 84 #include "inet.h"
 85 #include "dev.h"
 86 #include "ip.h"
 87 #include "protocol.h"
 88 #include "arp.h"
 89 #include "route.h"
 90 #include "tcp.h"
 91 #include "udp.h"
 92 #include "skbuff.h"
 93 #include "sock.h"
 94 #include "raw.h"
 95 #include "icmp.h"
 96 
 97 
 98 int inet_debug = DBG_OFF;               /* INET module debug flag       */
 99 
100 
101 #define min(a,b)        ((a)<(b)?(a):(b))
102 
103 extern struct proto packet_prot;
104 
105 
106 void
107 print_sk(struct sock *sk)
108 {
109   if (!sk) {
110         printk("  print_sk(NULL)\n");
111         return;
112   }
113   printk("  wmem_alloc = %lu\n", sk->wmem_alloc);
114   printk("  rmem_alloc = %lu\n", sk->rmem_alloc);
115   printk("  send_head = %p\n", sk->send_head);
116   printk("  state = %d\n",sk->state);
117   printk("  wback = %p, rqueue = %p\n", sk->wback, sk->rqueue);
118   printk("  wfront = %p\n", sk->wfront);
119   printk("  daddr = %lX, saddr = %lX\n", sk->daddr,sk->saddr);
120   printk("  num = %d", sk->num);
121   printk(" next = %p\n", sk->next);
122   printk("  write_seq = %ld, acked_seq = %ld, copied_seq = %ld\n",
123           sk->write_seq, sk->acked_seq, sk->copied_seq);
124   printk("  rcv_ack_seq = %ld, window_seq = %ld, fin_seq = %ld\n",
125           sk->rcv_ack_seq, sk->window_seq, sk->fin_seq);
126   printk("  prot = %p\n", sk->prot);
127   printk("  pair = %p, back_log = %p\n", sk->pair,sk->back_log);
128   printk("  inuse = %d , blog = %d\n", sk->inuse, sk->blog);
129   printk("  dead = %d delay_acks=%d\n", sk->dead, sk->delay_acks);
130   printk("  retransmits = %ld, timeout = %d\n", sk->retransmits, sk->timeout);
131   printk("  cong_window = %d, packets_out = %d\n", sk->cong_window,
132           sk->packets_out);
133   printk("  shutdown=%d\n", sk->shutdown);
134 }
135 
136 
137 void
138 print_skb(struct sk_buff *skb)
139 {
140   if (!skb) {
141         printk("  print_skb(NULL)\n");
142         return;
143   }
144   printk("  prev = %p, next = %p\n", skb->prev, skb->next);
145   printk("  sk = %p link3 = %p\n", skb->sk, skb->link3);
146   printk("  mem_addr = %p, mem_len = %lu\n", skb->mem_addr, skb->mem_len);
147   printk("  used = %d free = %d\n", skb->used,skb->free);
148 }
149 
150 
151 
152 static int
153 sk_inuse(struct proto *prot, int num)
154 {
155   struct sock *sk;
156 
157   for(sk = prot->sock_array[num & (SOCK_ARRAY_SIZE -1 )];
158       sk != NULL;
159       sk=sk->next) {
160         if (sk->num == num) return(1);
161   }
162   return(0);
163 }
164 
165 
166 unsigned short
167 get_new_socknum(struct proto *prot, unsigned short base)
168 {
169   static int start=0;
170 
171   /*
172    * Used to cycle through the port numbers so the
173    * chances of a confused connection drop.
174    */
175   int i, j;
176   int best = 0;
177   int size = 32767; /* a big num. */
178   struct sock *sk;
179 
180   if (base == 0) base = PROT_SOCK+1+(start % 1024);
181   if (base <= PROT_SOCK) {
182         base += PROT_SOCK+(start % 1024);
183   }
184 
185   /* Now look through the entire array and try to find an empty ptr. */
186   for(i=0; i < SOCK_ARRAY_SIZE; i++) {
187         j = 0;
188         sk = prot->sock_array[(i+base+1) &(SOCK_ARRAY_SIZE -1)];
189         while(sk != NULL) {
190                 sk = sk->next;
191                 j++;
192         }
193         if (j == 0) {
194                 start =(i+1+start )%1024;
195                 DPRINTF((DBG_INET, "get_new_socknum returning %d, start = %d\n",
196                                                         i + base + 1, start));
197                 return(i+base+1);
198         }
199         if (j < size) {
200                 best = i;
201                 size = j;
202         }
203   }
204 
205   /* Now make sure the one we want is not in use. */
206   while(sk_inuse(prot, base +best+1)) {
207         best += SOCK_ARRAY_SIZE;
208   }
209   DPRINTF((DBG_INET, "get_new_socknum returning %d, start = %d\n",
210                                                 best + base + 1, start));
211   return(best+base+1);
212 }
213 
214 
215 void
216 put_sock(unsigned short num, struct sock *sk)
217 {
218   struct sock *sk1;
219   struct sock *sk2;
220   int mask;
221 
222   DPRINTF((DBG_INET, "put_sock(num = %d, sk = %X\n", num, sk));
223   sk->num = num;
224   sk->next = NULL;
225   num = num &(SOCK_ARRAY_SIZE -1);
226 
227   /* We can't have an interupt re-enter here. */
228   cli();
229   if (sk->prot->sock_array[num] == NULL) {
230         sk->prot->sock_array[num] = sk;
231         sti();
232         return;
233   }
234   sti();
235   for(mask = 0xff000000; mask != 0xffffffff; mask = (mask >> 8) | mask) {
236         if ((mask & sk->saddr) &&
237             (mask & sk->saddr) != (mask & 0xffffffff)) {
238                 mask = mask << 8;
239                 break;
240         }
241   }
242   DPRINTF((DBG_INET, "mask = %X\n", mask));
243 
244   cli();
245   sk1 = sk->prot->sock_array[num];
246   for(sk2 = sk1; sk2 != NULL; sk2=sk2->next) {
247         if (!(sk2->saddr & mask)) {
248                 if (sk2 == sk1) {
249                         sk->next = sk->prot->sock_array[num];
250                         sk->prot->sock_array[num] = sk;
251                         sti();
252                         return;
253                 }
254                 sk->next = sk2;
255                 sk1->next= sk;
256                 sti();
257                 return;
258         }
259         sk1 = sk2;
260   }
261 
262   /* Goes at the end. */
263   sk->next = NULL;
264   sk1->next = sk;
265   sti();
266 }
267 
268 
269 static void
270 remove_sock(struct sock *sk1)
271 {
272   struct sock *sk2;
273 
274   DPRINTF((DBG_INET, "remove_sock(sk1=%X)\n", sk1));
275   if (!sk1) {
276         printk("sock.c: remove_sock: sk1 == NULL\n");
277         return;
278   }
279 
280   if (!sk1->prot) {
281         printk("sock.c: remove_sock: sk1->prot == NULL\n");
282         return;
283   }
284 
285   /* We can't have this changing out from under us. */
286   cli();
287   sk2 = sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)];
288   if (sk2 == sk1) {
289         sk1->prot->sock_array[sk1->num &(SOCK_ARRAY_SIZE -1)] = sk1->next;
290         sti();
291         return;
292   }
293 
294   while(sk2 && sk2->next != sk1) {
295         sk2 = sk2->next;
296   }
297 
298   if (sk2) {
299         sk2->next = sk1->next;
300         sti();
301         return;
302   }
303   sti();
304 
305   if (sk1->num != 0) DPRINTF((DBG_INET, "remove_sock: sock not found.\n"));
306 }
307 
308 
309 void
310 destroy_sock(struct sock *sk)
311 {
312         struct sk_buff *skb;
313 
314         DPRINTF((DBG_INET, "destroying socket %X\n", sk));
315         sk->inuse = 1;                  /* just to be safe. */
316 
317         /* Incase it's sleeping somewhere. */
318         if (!sk->dead) 
319                 sk->write_space(sk);
320 
321         remove_sock(sk);
322   
323         /* Now we can no longer get new packets. */
324         delete_timer(sk);
325 
326 
327         while ((skb = tcp_dequeue_partial(sk)) != NULL) 
328         {
329                 IS_SKB(skb);
330                 kfree_skb(skb, FREE_WRITE);
331         }
332 
333   /* Cleanup up the write buffer. */
334         for(skb = sk->wfront; skb != NULL; ) 
335         {
336                 struct sk_buff *skb2;
337 
338                 skb2=(struct sk_buff *)skb->next;
339                 if (skb->magic != TCP_WRITE_QUEUE_MAGIC) {
340                         printk("sock.c:destroy_sock write queue with bad magic(%X)\n",
341                                                                 skb->magic);
342                         break;
343                 }
344                 IS_SKB(skb);
345                 kfree_skb(skb, FREE_WRITE);
346                 skb = skb2;
347         }
348 
349         sk->wfront = NULL;
350         sk->wback = NULL;
351 
352         if (sk->rqueue != NULL) 
353         {
354                 while((skb=skb_dequeue(&sk->rqueue))!=NULL)
355                 {
356                 /*
357                  * This will take care of closing sockets that were
358                  * listening and didn't accept everything.
359                  */
360                         if (skb->sk != NULL && skb->sk != sk) 
361                         {
362                                 IS_SKB(skb);
363                                 skb->sk->dead = 1;
364                                 skb->sk->prot->close(skb->sk, 0);
365                         }
366                         IS_SKB(skb);
367                         kfree_skb(skb, FREE_READ);
368                 }
369         }
370         sk->rqueue = NULL;
371 
372   /* Now we need to clean up the send head. */
373         for(skb = sk->send_head; skb != NULL; ) 
374         {
375                 struct sk_buff *skb2;
376 
377                 /*
378                  * We need to remove skb from the transmit queue,
379                  * or maybe the arp queue.
380                  */

⌨️ 快捷键说明

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