OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_Demo_Rowley_ARM7/] [lwip-1.1.0/] [src/] [core/] [udp.c] - Blame information for rev 583

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 583 jeremybenn
/**
2
 * @file
3
 * User Datagram Protocol module
4
 *
5
 */
6
/*
7
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without modification,
11
 * are permitted provided that the following conditions are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright notice,
14
 *    this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright notice,
16
 *    this list of conditions and the following disclaimer in the documentation
17
 *    and/or other materials provided with the distribution.
18
 * 3. The name of the author may not be used to endorse or promote products
19
 *    derived from this software without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30
 * OF SUCH DAMAGE.
31
 *
32
 * This file is part of the lwIP TCP/IP stack.
33
 *
34
 * Author: Adam Dunkels <adam@sics.se>
35
 *
36
 */
37
 
38
 
39
/* udp.c
40
 *
41
 * The code for the User Datagram Protocol UDP.
42
 *
43
 */
44
 
45
#include <string.h>
46
 
47
#include "lwip/opt.h"
48
 
49
#include "lwip/def.h"
50
#include "lwip/memp.h"
51
#include "lwip/inet.h"
52
#include "lwip/ip_addr.h"
53
#include "lwip/netif.h"
54
#include "lwip/udp.h"
55
#include "lwip/icmp.h"
56
 
57
#include "lwip/stats.h"
58
 
59
#include "arch/perf.h"
60
#include "lwip/snmp.h"
61
 
62
/* The list of UDP PCBs */
63
#if LWIP_UDP
64
/* was static, but we may want to access this from a socket layer */
65
struct udp_pcb *udp_pcbs = NULL;
66
 
67
static struct udp_pcb *pcb_cache = NULL;
68
 
69
 
70
void
71
udp_init(void)
72
{
73
  udp_pcbs = pcb_cache = NULL;
74
}
75
 
76
/**
77
 * Process an incoming UDP datagram.
78
 *
79
 * Given an incoming UDP datagram (as a chain of pbufs) this function
80
 * finds a corresponding UDP PCB and
81
 *
82
 * @param pbuf pbuf to be demultiplexed to a UDP PCB.
83
 * @param netif network interface on which the datagram was received.
84
 *
85
 */
86
void
87
udp_input(struct pbuf *p, struct netif *inp)
88
{
89
  struct udp_hdr *udphdr;
90
  struct udp_pcb *pcb;
91
  struct ip_hdr *iphdr;
92
  u16_t src, dest;
93
 
94
#if SO_REUSE
95
  struct udp_pcb *pcb_temp;
96
  int reuse = 0;
97
  int reuse_port_1 = 0;
98
  int reuse_port_2 = 0;
99
#endif /* SO_REUSE */
100
 
101
  PERF_START;
102
 
103
  UDP_STATS_INC(udp.recv);
104
 
105
  iphdr = p->payload;
106
 
107
  if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
108
    /* drop short packets */
109
    LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
110
    UDP_STATS_INC(udp.lenerr);
111
    UDP_STATS_INC(udp.drop);
112
    snmp_inc_udpinerrors();
113
    pbuf_free(p);
114
    goto end;
115
  }
116
 
117
  udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
118
 
119
  LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %u\n", p->tot_len));
120
 
121
  src = ntohs(udphdr->src);
122
  dest = ntohs(udphdr->dest);
123
 
124
  udp_debug_print(udphdr);
125
 
126
  /* print the UDP source and destination */
127
  LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
128
    ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
129
    ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
130
    ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
131
    ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
132
 
133
#if SO_REUSE
134
  pcb_temp = udp_pcbs;
135
 
136
 again_1:
137
 
138
  /* Iterate through the UDP pcb list for a fully matching pcb */
139
  for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
140
#else  /* SO_REUSE */ 
141
  /* Iterate through the UDP pcb list for a fully matching pcb */
142
  for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
143
#endif  /* SO_REUSE */ 
144
    /* print the PCB local and remote address */
145
    LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
146
      ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
147
      ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
148
      ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
149
      ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
150
 
151
       /* PCB remote port matches UDP source port? */
152
    if ((pcb->remote_port == src) &&
153
       /* PCB local port matches UDP destination port? */
154
       (pcb->local_port == dest) &&
155
       /* accepting from any remote (source) IP address? or... */
156
       (ip_addr_isany(&pcb->remote_ip) ||
157
       /* PCB remote IP address matches UDP source IP address? */
158
        ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
159
       /* accepting on any local (netif) IP address? or... */
160
       (ip_addr_isany(&pcb->local_ip) ||
161
       /* PCB local IP address matches UDP destination IP address? */
162
        ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
163
#if SO_REUSE
164
      if (pcb->so_options & SOF_REUSEPORT) {
165
        if(reuse) {
166
          /* We processed one PCB already */
167
          LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
168
        } else {
169
          /* First PCB with this address */
170
          LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
171
          reuse = 1;
172
        }
173
 
174
        reuse_port_1 = 1;
175
        p->ref++;
176
        LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
177
      } else {
178
        if (reuse) {
179
          /* We processed one PCB already */
180
          LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
181
        }
182
      }
183
#endif /* SO_REUSE */
184
      break;
185
    }
186
  }
187
  /* no fully matching pcb found? then look for an unconnected pcb */
188
  if (pcb == NULL) {
189
    /* Iterate through the UDP PCB list for a pcb that matches
190
       the local address. */
191
 
192
#if SO_REUSE
193
    pcb_temp = udp_pcbs;
194
 
195
  again_2:
196
 
197
    for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
198
#else  /* SO_REUSE */ 
199
    for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
200
#endif  /* SO_REUSE */ 
201
      LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
202
        ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
203
        ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
204
        ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
205
        ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
206
      /* unconnected? */
207
      if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) &&
208
         /* destination port matches? */
209
        (pcb->local_port == dest) &&
210
        /* not bound to a specific (local) interface address? or... */
211
        (ip_addr_isany(&pcb->local_ip) ||
212
        /* ...matching interface address? */
213
        ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
214
#if SO_REUSE
215
        if (pcb->so_options & SOF_REUSEPORT) {
216
          if (reuse) {
217
            /* We processed one PCB already */
218
            LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
219
          } else {
220
            /* First PCB with this address */
221
            LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
222
            reuse = 1;
223
          }
224
 
225
          reuse_port_2 = 1;
226
          p->ref++;
227
          LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
228
        } else {
229
          if (reuse) {
230
            /* We processed one PCB already */
231
            LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
232
          }
233
        }
234
#endif /* SO_REUSE */
235
        break;
236
      }
237
    }
238
  }
239
 
240
  /* Check checksum if this is a match or if it was directed at us. */
241
  if (pcb != NULL  || ip_addr_cmp(&inp->ip_addr, &iphdr->dest))
242
    {
243
    LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: calculating checksum\n"));
244
    pbuf_header(p, UDP_HLEN);
245
#ifdef IPv6
246
    if (iphdr->nexthdr == IP_PROTO_UDPLITE) {
247
#else
248
    if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
249
#endif /* IPv4 */
250
      /* Do the UDP Lite checksum */
251
#if CHECKSUM_CHECK_UDP
252
      if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
253
         (struct ip_addr *)&(iphdr->dest),
254
         IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
255
  LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
256
  UDP_STATS_INC(udp.chkerr);
257
  UDP_STATS_INC(udp.drop);
258
  snmp_inc_udpinerrors();
259
  pbuf_free(p);
260
  goto end;
261
      }
262
#endif
263
    } else {
264
#if CHECKSUM_CHECK_UDP
265
      if (udphdr->chksum != 0) {
266
  if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
267
       (struct ip_addr *)&(iphdr->dest),
268
        IP_PROTO_UDP, p->tot_len) != 0) {
269
    LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
270
 
271
    UDP_STATS_INC(udp.chkerr);
272
    UDP_STATS_INC(udp.drop);
273
    snmp_inc_udpinerrors();
274
    pbuf_free(p);
275
    goto end;
276
  }
277
      }
278
#endif
279
    }
280
    pbuf_header(p, -UDP_HLEN);
281
    if (pcb != NULL) {
282
      snmp_inc_udpindatagrams();
283
      pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
284
#if SO_REUSE
285
      /* First socket should receive now */
286
      if(reuse_port_1 || reuse_port_2) {
287
        /* We want to search on next socket after receiving */
288
        pcb_temp = pcb->next;
289
 
290
        if(reuse_port_1) {
291
          /* We are searching connected sockets */
292
          reuse_port_1 = 0;
293
          reuse_port_2 = 0;
294
          goto again_1;
295
        } else {
296
          /* We are searching unconnected sockets */
297
          reuse_port_1 = 0;
298
          reuse_port_2 = 0;
299
          goto again_2;
300
        }
301
      }
302
#endif /* SO_REUSE */ 
303
    } else {
304
#if SO_REUSE
305
      if(reuse) {
306
        LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
307
        pbuf_free(p);
308
        goto end;
309
      }
310
#endif /* SO_REUSE */
311
      LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
312
 
313
      /* No match was found, send ICMP destination port unreachable unless
314
      destination address was broadcast/multicast. */
315
 
316
      if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
317
          !ip_addr_ismulticast(&iphdr->dest)) {
318
 
319
  /* adjust pbuf pointer */
320
  p->payload = iphdr;
321
  icmp_dest_unreach(p, ICMP_DUR_PORT);
322
      }
323
      UDP_STATS_INC(udp.proterr);
324
      UDP_STATS_INC(udp.drop);
325
    snmp_inc_udpnoports();
326
      pbuf_free(p);
327
    }
328
  } else {
329
    pbuf_free(p);
330
  }
331
  end:
332
 
333
  PERF_STOP("udp_input");
334
}
335
 
336
/**
337
 * Send data to a specified address using UDP.
338
 *
339
 * @param pcb UDP PCB used to send the data.
340
 * @param pbuf chain of pbuf's to be sent.
341
 * @param dst_ip Destination IP address.
342
 * @param dst_port Destination UDP port.
343
 *
344
 * If the PCB already has a remote address association, it will
345
 * be restored after the data is sent.
346
 *
347
 * @return lwIP error code.
348
 * - ERR_OK. Successful. No error occured.
349
 * - ERR_MEM. Out of memory.
350
 * - ERR_RTE. Could not find route to destination address.
351
 *
352
 * @see udp_disconnect() udp_send()
353
 */
354
err_t
355
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
356
  struct ip_addr *dst_ip, u16_t dst_port)
357
{
358
  err_t err;
359
  /* temporary space for current PCB remote address */
360
  struct ip_addr pcb_remote_ip;
361
  u16_t pcb_remote_port;
362
  /* remember current remote peer address of PCB */
363
  pcb_remote_ip.addr = pcb->remote_ip.addr;
364
  pcb_remote_port = pcb->remote_port;
365
  /* copy packet destination address to PCB remote peer address */
366
  pcb->remote_ip.addr = dst_ip->addr;
367
  pcb->remote_port = dst_port;
368
  /* send to the packet destination address */
369
  err = udp_send(pcb, p);
370
  /* restore PCB remote peer address */
371
  pcb->remote_ip.addr = pcb_remote_ip.addr;
372
  pcb->remote_port = pcb_remote_port;
373
  return err;
374
}
375
 
376
/**
377
 * Send data using UDP.
378
 *
379
 * @param pcb UDP PCB used to send the data.
380
 * @param pbuf chain of pbuf's to be sent.
381
 *
382
 * @return lwIP error code.
383
 * - ERR_OK. Successful. No error occured.
384
 * - ERR_MEM. Out of memory.
385
 * - ERR_RTE. Could not find route to destination address.
386
 *
387
 * @see udp_disconnect() udp_sendto()
388
 */
389
err_t
390
udp_send(struct udp_pcb *pcb, struct pbuf *p)
391
{
392
  struct udp_hdr *udphdr;
393
  struct netif *netif;
394
  struct ip_addr *src_ip;
395
  err_t err;
396
  struct pbuf *q; /* q will be sent down the stack */
397
 
398
  LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_send\n"));
399
 
400
  /* if the PCB is not yet bound to a port, bind it here */
401
  if (pcb->local_port == 0) {
402
    LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));
403
    err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
404
    if (err != ERR_OK) {
405
      LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: forced port bind failed\n"));
406
      return err;
407
    }
408
  }
409
 
410
  /* not enough space to add an UDP header to first pbuf in given p chain? */
411
  if (pbuf_header(p, UDP_HLEN)) {
412
    /* allocate header in a seperate new pbuf */
413
    q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
414
    /* new header pbuf could not be allocated? */
415
    if (q == NULL) {
416
      LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: could not allocate header\n"));
417
      return ERR_MEM;
418
    }
419
    /* chain header q in front of given pbuf p */
420
    pbuf_chain(q, p);
421
    /* { first pbuf q points to header pbuf } */
422
    LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
423
  /* adding a header within p succeeded */
424
  } else {
425
    /* first pbuf q equals given pbuf */
426
    q = p;
427
    LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
428
  }
429
  /* { q now represents the packet to be sent } */
430
  udphdr = q->payload;
431
  udphdr->src = htons(pcb->local_port);
432
  udphdr->dest = htons(pcb->remote_port);
433
  /* in UDP, 0 checksum means 'no checksum' */
434
  udphdr->chksum = 0x0000;
435
 
436
  /* find the outgoing network interface for this packet */
437
  netif = ip_route(&(pcb->remote_ip));
438
  /* no outgoing network interface could be found? */
439
  if (netif == NULL) {
440
    LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
441
    UDP_STATS_INC(udp.rterr);
442
    return ERR_RTE;
443
  }
444
  /* PCB local address is IP_ANY_ADDR? */
445
  if (ip_addr_isany(&pcb->local_ip)) {
446
    /* use outgoing network interface IP address as source address */
447
    src_ip = &(netif->ip_addr);
448
  } else {
449
    /* use UDP PCB local IP address as source address */
450
    src_ip = &(pcb->local_ip);
451
  }
452
 
453
  LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %u\n", q->tot_len));
454
 
455
  /* UDP Lite protocol? */
456
  if (pcb->flags & UDP_FLAGS_UDPLITE) {
457
    LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u\n", q->tot_len));
458
    /* set UDP message length in UDP header */
459
    udphdr->len = htons(pcb->chksum_len);
460
    /* calculate checksum */
461
#if CHECKSUM_GEN_UDP
462
    udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
463
          IP_PROTO_UDP, pcb->chksum_len);
464
    /* chksum zero must become 0xffff, as zero means 'no checksum' */
465
    if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
466
#else
467
    udphdr->chksum = 0x0000;
468
#endif
469
    /* output to IP */
470
    LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
471
    err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
472
  /* UDP */
473
  } else {
474
    LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
475
    udphdr->len = htons(q->tot_len);
476
    /* calculate checksum */
477
#if CHECKSUM_GEN_UDP
478
    if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
479
      udphdr->chksum = inet_chksum_pseudo(q, src_ip, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len);
480
      /* chksum zero must become 0xffff, as zero means 'no checksum' */
481
      if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
482
    }
483
#else
484
    udphdr->chksum = 0x0000;
485
#endif
486
    LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum));
487
    LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
488
    /* output to IP */
489
    err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
490
  }
491
  /* TODO: must this be increased even if error occured? */
492
  snmp_inc_udpoutdatagrams();
493
 
494
  /* did we chain a seperate header pbuf earlier? */
495
  if (q != p) {
496
    /* free the header pbuf */
497
    pbuf_free(q); q = NULL;
498
    /* { p is still referenced by the caller, and will live on } */
499
  }
500
 
501
  UDP_STATS_INC(udp.xmit);
502
  return err;
503
}
504
 
505
/**
506
 * Bind an UDP PCB.
507
 *
508
 * @param pcb UDP PCB to be bound with a local address ipaddr and port.
509
 * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
510
 * bind to all local interfaces.
511
 * @param port local UDP port to bind with.
512
 *
513
 * @return lwIP error code.
514
 * - ERR_OK. Successful. No error occured.
515
 * - ERR_USE. The specified ipaddr and port are already bound to by
516
 * another UDP PCB.
517
 *
518
 * @see udp_disconnect()
519
 */
520
err_t
521
udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
522
{
523
  struct udp_pcb *ipcb;
524
  u8_t rebind;
525
#if SO_REUSE
526
  int reuse_port_all_set = 1;
527
#endif /* SO_REUSE */
528
  LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
529
  ip_addr_debug_print(UDP_DEBUG, ipaddr);
530
  LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
531
 
532
  rebind = 0;
533
  /* Check for double bind and rebind of the same pcb */
534
  for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
535
    /* is this UDP PCB already on active list? */
536
    if (pcb == ipcb) {
537
      /* pcb may occur at most once in active list */
538
      LWIP_ASSERT("rebind == 0", rebind == 0);
539
      /* pcb already in list, just rebind */
540
      rebind = 1;
541
    }
542
 
543
#if SO_REUSE == 0
544
/* this code does not allow upper layer to share a UDP port for
545
   listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
546
   SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
547
   combine with implementation of UDP PCB flags. Leon Woestenberg. */
548
#ifdef LWIP_UDP_TODO
549
    /* port matches that of PCB in list? */
550
    else if ((ipcb->local_port == port) &&
551
       /* IP address matches, or one is IP_ADDR_ANY? */
552
       (ip_addr_isany(&(ipcb->local_ip)) ||
553
       ip_addr_isany(ipaddr) ||
554
       ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
555
      /* other PCB already binds to this local IP and port */
556
      LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %u already bound by another pcb\n", port));
557
      return ERR_USE;
558
    }
559
#endif
560
 
561
#else /* SO_REUSE */
562
      /* Search through list of PCB's.
563
 
564
      If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
565
      or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
566
      the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
567
      But no two PCB's bound to same local port and same local address is valid.
568
 
569
      If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
570
      all PCB's must have the SOF_REUSEPORT option set.
571
 
572
      When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
573
      address is already in use. */
574
    else if (ipcb->local_port == port) {
575
      if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
576
        if(pcb->so_options & SOF_REUSEPORT) {
577
          LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
578
          reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
579
        }
580
        else {
581
          LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
582
          return ERR_USE;
583
        }
584
      }
585
      else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
586
              (!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
587
        if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
588
          LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
589
          return ERR_USE;
590
        }
591
      }
592
    }
593
#endif /* SO_REUSE */
594
 
595
  }
596
 
597
#if SO_REUSE
598
  /* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
599
     {IP, port} can't be reused. */
600
  if(!reuse_port_all_set) {
601
    LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
602
    return ERR_USE;
603
  }
604
#endif /* SO_REUSE */
605
 
606
  ip_addr_set(&pcb->local_ip, ipaddr);
607
  /* no port specified? */
608
  if (port == 0) {
609
#ifndef UDP_LOCAL_PORT_RANGE_START
610
#define UDP_LOCAL_PORT_RANGE_START 4096
611
#define UDP_LOCAL_PORT_RANGE_END   0x7fff
612
#endif
613
    port = UDP_LOCAL_PORT_RANGE_START;
614
    ipcb = udp_pcbs;
615
    while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) {
616
      if (ipcb->local_port == port) {
617
        port++;
618
        ipcb = udp_pcbs;
619
      } else
620
        ipcb = ipcb->next;
621
    }
622
    if (ipcb != NULL) {
623
      /* no more ports available in local range */
624
      LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
625
      return ERR_USE;
626
    }
627
  }
628
  pcb->local_port = port;
629
  /* pcb not active yet? */
630
  if (rebind == 0) {
631
    /* place the PCB on the active list if not already there */
632
    pcb->next = udp_pcbs;
633
    udp_pcbs = pcb;
634
  }
635
  LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %u.%u.%u.%u, port %u\n",
636
   (unsigned int)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
637
   (unsigned int)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
638
   (unsigned int)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
639
   (unsigned int)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
640
  return ERR_OK;
641
}
642
/**
643
 * Connect an UDP PCB.
644
 *
645
 * This will associate the UDP PCB with the remote address.
646
 *
647
 * @param pcb UDP PCB to be connected with remote address ipaddr and port.
648
 * @param ipaddr remote IP address to connect with.
649
 * @param port remote UDP port to connect with.
650
 *
651
 * @return lwIP error code
652
 *
653
 * @see udp_disconnect()
654
 */
655
err_t
656
udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
657
{
658
  struct udp_pcb *ipcb;
659
 
660
  if (pcb->local_port == 0) {
661
    err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
662
    if (err != ERR_OK)
663
      return err;
664
  }
665
 
666
  ip_addr_set(&pcb->remote_ip, ipaddr);
667
  pcb->remote_port = port;
668
  pcb->flags |= UDP_FLAGS_CONNECTED;
669
/** TODO: this functionality belongs in upper layers */
670
#ifdef LWIP_UDP_TODO
671
  /* Nail down local IP for netconn_addr()/getsockname() */
672
  if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
673
    struct netif *netif;
674
 
675
    if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
676
      LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
677
        UDP_STATS_INC(udp.rterr);
678
      return ERR_RTE;
679
    }
680
    /** TODO: this will bind the udp pcb locally, to the interface which
681
        is used to route output packets to the remote address. However, we
682
        might want to accept incoming packets on any interface! */
683
    pcb->local_ip = netif->ip_addr;
684
  } else if (ip_addr_isany(&pcb->remote_ip)) {
685
    pcb->local_ip.addr = 0;
686
  }
687
#endif
688
  LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %u.%u.%u.%u, port %u\n",
689
   (unsigned int)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
690
   (unsigned int)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
691
   (unsigned int)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
692
   (unsigned int)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
693
 
694
  /* Insert UDP PCB into the list of active UDP PCBs. */
695
  for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
696
    if (pcb == ipcb) {
697
      /* already on the list, just return */
698
      return ERR_OK;
699
    }
700
  }
701
  /* PCB not yet on the list, add PCB now */
702
  pcb->next = udp_pcbs;
703
  udp_pcbs = pcb;
704
  return ERR_OK;
705
}
706
 
707
void
708
udp_disconnect(struct udp_pcb *pcb)
709
{
710
  /* reset remote address association */
711
  ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY);
712
  pcb->remote_port = 0;
713
  /* mark PCB as unconnected */
714
  pcb->flags &= ~UDP_FLAGS_CONNECTED;
715
}
716
 
717
void
718
udp_recv(struct udp_pcb *pcb,
719
   void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
720
           struct ip_addr *addr, u16_t port),
721
   void *recv_arg)
722
{
723
  /* remember recv() callback and user data */
724
  pcb->recv = recv;
725
  pcb->recv_arg = recv_arg;
726
}
727
/**
728
 * Remove an UDP PCB.
729
 *
730
 * @param pcb UDP PCB to be removed. The PCB is removed from the list of
731
 * UDP PCB's and the data structure is freed from memory.
732
 *
733
 * @see udp_new()
734
 */
735
void
736
udp_remove(struct udp_pcb *pcb)
737
{
738
  struct udp_pcb *pcb2;
739
  /* pcb to be removed is first in list? */
740
  if (udp_pcbs == pcb) {
741
    /* make list start at 2nd pcb */
742
    udp_pcbs = udp_pcbs->next;
743
  /* pcb not 1st in list */
744
  } else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
745
    /* find pcb in udp_pcbs list */
746
    if (pcb2->next != NULL && pcb2->next == pcb) {
747
      /* remove pcb from list */
748
      pcb2->next = pcb->next;
749
    }
750
  }
751
  memp_free(MEMP_UDP_PCB, pcb);
752
}
753
/**
754
 * Create a UDP PCB.
755
 *
756
 * @return The UDP PCB which was created. NULL if the PCB data structure
757
 * could not be allocated.
758
 *
759
 * @see udp_remove()
760
 */
761
struct udp_pcb *
762
udp_new(void) {
763
  struct udp_pcb *pcb;
764
  pcb = memp_malloc(MEMP_UDP_PCB);
765
  /* could allocate UDP PCB? */
766
  if (pcb != NULL) {
767
    /* initialize PCB to all zeroes */
768
    memset(pcb, 0, sizeof(struct udp_pcb));
769
    pcb->ttl = UDP_TTL;
770
  }
771
 
772
 
773
  return pcb;
774
}
775
 
776
#if UDP_DEBUG
777
int
778
udp_debug_print(struct udp_hdr *udphdr)
779
{
780
  LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
781
  LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
782
  LWIP_DEBUGF(UDP_DEBUG, ("|     %5u     |     %5u     | (src port, dest port)\n",
783
         ntohs(udphdr->src), ntohs(udphdr->dest)));
784
  LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
785
  LWIP_DEBUGF(UDP_DEBUG, ("|     %5u     |     0x%04x    | (len, chksum)\n",
786
         ntohs(udphdr->len), ntohs(udphdr->chksum)));
787
  LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
788
  return 0;
789
}
790
#endif /* UDP_DEBUG */
791
 
792
#endif /* LWIP_UDP */
793
 
794
 
795
 
796
 
797
 
798
 
799
 
800
 
801
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.