Free (GPLv2) TCP/IP stack developed by TASS Belgium
Dependents: lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more
pico_socket_udp.c
00001 #include "pico_config.h" 00002 #include "pico_socket.h" 00003 #include "pico_udp.h" 00004 #include "pico_socket_multicast.h" 00005 #include "pico_ipv4.h" 00006 #include "pico_ipv6.h" 00007 #include "pico_socket_udp.h" 00008 00009 #define UDP_FRAME_OVERHEAD (sizeof(struct pico_frame)) 00010 00011 00012 struct pico_socket *pico_socket_udp_open(void) 00013 { 00014 struct pico_socket *s = NULL; 00015 #ifdef PICO_SUPPORT_UDP 00016 s = pico_udp_open(); 00017 if (!s) { 00018 pico_err = PICO_ERR_ENOMEM; 00019 return NULL; 00020 } 00021 00022 s->proto = &pico_proto_udp; 00023 s->q_in.overhead = UDP_FRAME_OVERHEAD; 00024 s->q_out.overhead = UDP_FRAME_OVERHEAD; 00025 #endif 00026 return s; 00027 } 00028 00029 00030 #ifdef PICO_SUPPORT_IPV4 00031 static inline int pico_socket_udp_deliver_ipv4_mcast_initial_checks(struct pico_socket *s, struct pico_frame *f) 00032 { 00033 struct pico_ip4 p_dst; 00034 struct pico_ipv4_hdr *ip4hdr; 00035 00036 ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr); 00037 p_dst.addr = ip4hdr->dst.addr; 00038 if (pico_ipv4_is_multicast(p_dst.addr) && (pico_socket_mcast_filter(s, (union pico_address *)&ip4hdr->dst, (union pico_address *)&ip4hdr->src) < 0)) 00039 return -1; 00040 00041 00042 if ((pico_ipv4_link_get(&ip4hdr->src)) && (PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_MULTICAST_LOOP) == 0u)) { 00043 /* Datagram from ourselves, Loop disabled, discarding. */ 00044 return -1; 00045 } 00046 00047 return 0; 00048 } 00049 00050 00051 static int pico_socket_udp_deliver_ipv4_mcast(struct pico_socket *s, struct pico_frame *f) 00052 { 00053 struct pico_ip4 s_local; 00054 struct pico_frame *cpy; 00055 struct pico_device *dev = pico_ipv4_link_find(&s->local_addr.ip4); 00056 00057 s_local.addr = s->local_addr.ip4.addr; 00058 00059 if (pico_socket_udp_deliver_ipv4_mcast_initial_checks(s, f) < 0) 00060 return 0; 00061 00062 if ((s_local.addr == PICO_IPV4_INADDR_ANY) || /* If our local ip is ANY, or.. */ 00063 (dev == f->dev)) { /* the source of the bcast packet is a neighbor... */ 00064 cpy = pico_frame_copy(f); 00065 if (!cpy) 00066 return -1; 00067 00068 if (pico_enqueue(&s->q_in, cpy) > 0) { 00069 if (s->wakeup) 00070 s->wakeup(PICO_SOCK_EV_RD, s); 00071 } 00072 else 00073 pico_frame_discard(cpy); 00074 } 00075 00076 return 0; 00077 } 00078 00079 static int pico_socket_udp_deliver_ipv4_unicast(struct pico_socket *s, struct pico_frame *f) 00080 { 00081 struct pico_frame *cpy; 00082 /* Either local socket is ANY, or matches dst */ 00083 cpy = pico_frame_copy(f); 00084 if (!cpy) 00085 return -1; 00086 00087 if (pico_enqueue(&s->q_in, cpy) > 0) { 00088 if (s->wakeup) 00089 s->wakeup(PICO_SOCK_EV_RD, s); 00090 } else { 00091 pico_frame_discard(cpy); 00092 } 00093 00094 return 0; 00095 } 00096 00097 00098 static int pico_socket_udp_deliver_ipv4(struct pico_socket *s, struct pico_frame *f) 00099 { 00100 int ret = 0; 00101 struct pico_ip4 s_local, p_dst; 00102 struct pico_ipv4_hdr *ip4hdr; 00103 ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr); 00104 s_local.addr = s->local_addr.ip4.addr; 00105 p_dst.addr = ip4hdr->dst.addr; 00106 if ((pico_ipv4_is_broadcast(p_dst.addr)) || pico_ipv4_is_multicast(p_dst.addr)) { 00107 ret = pico_socket_udp_deliver_ipv4_mcast(s, f); 00108 } else if ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr)) { 00109 ret = pico_socket_udp_deliver_ipv4_unicast(s, f); 00110 } 00111 00112 pico_frame_discard(f); 00113 return ret; 00114 } 00115 #endif 00116 00117 #ifdef PICO_SUPPORT_IPV6 00118 static inline int pico_socket_udp_deliver_ipv6_mcast(struct pico_socket *s, struct pico_frame *f) 00119 { 00120 struct pico_ipv6_hdr *ip6hdr; 00121 struct pico_frame *cpy; 00122 struct pico_device *dev = pico_ipv6_link_find(&s->local_addr.ip6); 00123 00124 ip6hdr = (struct pico_ipv6_hdr*)(f->net_hdr); 00125 00126 if ((pico_ipv6_link_get(&ip6hdr->src)) && (PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_MULTICAST_LOOP) == 0u)) { 00127 /* Datagram from ourselves, Loop disabled, discarding. */ 00128 return 0; 00129 } 00130 00131 00132 if (pico_ipv6_is_unspecified(s->local_addr.ip6.addr) || /* If our local ip is ANY, or.. */ 00133 (dev == f->dev)) { /* the source of the bcast packet is a neighbor... */ 00134 cpy = pico_frame_copy(f); 00135 if (!cpy) 00136 { 00137 return -1; 00138 } 00139 00140 if (pico_enqueue(&s->q_in, cpy) > 0) { 00141 if (s->wakeup) 00142 s->wakeup(PICO_SOCK_EV_RD, s); 00143 } 00144 else 00145 pico_frame_discard(cpy); 00146 } 00147 00148 return 0; 00149 } 00150 00151 static int pico_socket_udp_deliver_ipv6(struct pico_socket *s, struct pico_frame *f) 00152 { 00153 struct pico_ip6 s_local, p_dst; 00154 struct pico_ipv6_hdr *ip6hdr; 00155 struct pico_frame *cpy; 00156 ip6hdr = (struct pico_ipv6_hdr*)(f->net_hdr); 00157 s_local = s->local_addr.ip6; 00158 p_dst = ip6hdr->dst; 00159 if ((pico_ipv6_is_multicast(p_dst.addr))) { 00160 int retval = pico_socket_udp_deliver_ipv6_mcast(s, f); 00161 pico_frame_discard(f); 00162 return retval; 00163 } 00164 else if (pico_ipv6_is_unspecified(s->local_addr.ip6.addr) || (pico_ipv6_compare(&s_local, &p_dst) == 0)) 00165 { /* Either local socket is ANY, or matches dst */ 00166 cpy = pico_frame_copy(f); 00167 if (!cpy) 00168 { 00169 pico_frame_discard(f); 00170 return -1; 00171 } 00172 00173 if (pico_enqueue(&s->q_in, cpy) > 0) { 00174 if (s->wakeup) 00175 s->wakeup(PICO_SOCK_EV_RD, s); 00176 } 00177 } 00178 00179 pico_frame_discard(f); 00180 return 0; 00181 } 00182 #endif 00183 00184 00185 int pico_socket_udp_deliver(struct pico_sockport *sp, struct pico_frame *f) 00186 { 00187 struct pico_tree_node *index = NULL; 00188 struct pico_tree_node *_tmp; 00189 struct pico_socket *s = NULL; 00190 pico_err = PICO_ERR_EPROTONOSUPPORT; 00191 #ifdef PICO_SUPPORT_UDP 00192 pico_err = PICO_ERR_NOERR; 00193 pico_tree_foreach_safe(index, &sp->socks, _tmp){ 00194 s = index->keyValue; 00195 if (IS_IPV4(f)) { /* IPV4 */ 00196 #ifdef PICO_SUPPORT_IPV4 00197 return pico_socket_udp_deliver_ipv4(s, f); 00198 #endif 00199 } else if (IS_IPV6(f)) { 00200 #ifdef PICO_SUPPORT_IPV6 00201 return pico_socket_udp_deliver_ipv6(s, f); 00202 #endif 00203 } else { 00204 /* something wrong in the packet header*/ 00205 } 00206 } /* FOREACH */ 00207 pico_frame_discard(f); 00208 if (s) 00209 return 0; 00210 00211 pico_err = PICO_ERR_ENXIO; 00212 #endif 00213 return -1; 00214 } 00215 00216 int pico_setsockopt_udp(struct pico_socket *s, int option, void *value) 00217 { 00218 switch(option) { 00219 case PICO_SOCKET_OPT_RCVBUF: 00220 s->q_in.max_size = (*(uint32_t*)value); 00221 return 0; 00222 case PICO_SOCKET_OPT_SNDBUF: 00223 s->q_out.max_size = (*(uint32_t*)value); 00224 return 0; 00225 } 00226 00227 /* switch's default */ 00228 #ifdef PICO_SUPPORT_MCAST 00229 return pico_setsockopt_mcast(s, option, value); 00230 #else 00231 pico_err = PICO_ERR_EINVAL; 00232 return -1; 00233 #endif 00234 } 00235 00236 int pico_getsockopt_udp(struct pico_socket *s, int option, void *value) 00237 { 00238 uint32_t *val = (uint32_t *)value; 00239 switch(option) { 00240 case PICO_SOCKET_OPT_RCVBUF: 00241 *val = s->q_in.max_size; 00242 return 0; 00243 case PICO_SOCKET_OPT_SNDBUF: 00244 *val = s->q_out.max_size; 00245 return 0; 00246 } 00247 00248 /* switch's default */ 00249 #ifdef PICO_SUPPORT_MCAST 00250 return pico_getsockopt_mcast(s, option, value); 00251 #else 00252 pico_err = PICO_ERR_EINVAL; 00253 return -1; 00254 #endif 00255 } 00256
Generated on Tue Jul 12 2022 15:59:22 by 1.7.2