/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_sock_ip4.c,v $ $Revision: 1.51.10.13 $ * $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_sock_ip4.c,v $ * $Author: jren $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** * IPv4 specific socket operations. */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifndef IPCOM_KERNEL #define IPCOM_KERNEL #endif #include "ipnet_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include "ipnet_h.h" #include "ipnet_usr_sock.h" #ifdef IPSCTP #include "ipsctp.h" #endif #ifdef IPIPSEC2 #include "ipipsec.h" #endif #ifdef IPNET_USE_PER_SOCKET_VLAN_TAG #include "ipnet_eth.h" /* ipnet_vlan_set_tag() */ #endif #ifdef IPCOM_USE_INET /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_sock_ip4_init *=========================================================================== * Description: IPv4 specific initialization. * Parameters: sock - The socket that is beeing created. * Returns: 0 for success else negative error code. * */ IP_STATIC int ipnet_sock_ip4_init(Ipnet_socket *sock, Ip_bool user_context) { IPCOM_UNUSED_ARG(user_context); /* * Let the stack select the TTL form the per-interface * configuration set via sysvar [ipnet|].inet.BaseHopLimit */ sock->uni_hop_limit = 0; sock->ip4 = ipnet_sock_alloc_private_data(sock, sizeof(Ipnet_ip4_socket)); #ifndef IPNET_USE_RESTRICTED_SOCKET_BROADCAST IP_BIT_SET(sock->ip4->flags, IPNET_SOCKET_FLAG_IP4_ALLOW_BROADCAST); #endif #ifdef IPSCTP if (IP_NULL != sock->sctp_inst) IP_BIT_SET(sock->sctp_inst->inst_flags, IPSCTP_SOCKET_BOUND_V4); #endif switch (sock->ipcom.type) { case IP_SOCK_RAW: if (sock->proto == IP_IPPROTO_ICMP) { sock->ip4->icmp_filter = ipnet_sock_alloc_private_data(sock, sizeof(struct Ip_icmp_filter)); IP_ICMP_FILTER_SETPASSALL(sock->ip4->icmp_filter); } break; case IP_SOCK_STREAM: case IP_SOCK_SEQPACKET: sock->ip4->dont_frag = ipnet->conf.inet.sock_stream_dont_frag; return 0; case IP_SOCK_DGRAM: return 0; default: IP_PANIC2(); return -IP_ERRNO_EINVAL; } return ipnet_sock_set_reachable(sock); } /* *=========================================================================== * ipnet_sock_ip4_destroy *=========================================================================== * Description: IPv4 specific cleanup during socket close. * Parameters: sock - The socket that is beeing closed. * Returns: * */ IP_STATIC void ipnet_sock_ip4_destroy(Ipnet_socket *sock) { ipnet_sock_unbind(sock); ipcom_free(sock->ip4->opts); #ifdef IPNET_USE_MCAST_ROUTING if (IP_BIT_ISSET(sock->flags, IPNET_SOCKET_FLAG_MROUTE_CONTROL)) ipnet_ip4_mcast_mrt_done(sock); #endif } /* *=========================================================================== * ipnet_sock_ip4_connect *=========================================================================== * Description: The IPv4 network layer connect. * Parameters: sock - The socket to connect. * to - The address to connect to. * tolen - The size of the 'to' buffer. * Returns: 0 = success, <0 = error code * */ IP_STATIC int ipnet_sock_ip4_connect(Ipnet_socket *sock, IP_CONST struct Ip_sockaddr *to, Ip_socklen_t tolen) { struct Ip_sockaddr_in in_name; struct Ip_sockaddr_in *in_to; IP_CONST struct Ip_in_addr *src_addr; Ip_u16 sport = 0; Ipnet_netif *netif = IP_NULL; ipnet_sock_set_unreachable(sock); sock->ip4->daddr_n = 0; switch (to->sa_family) { case IP_AF_INET: /* Setup the IPv4 destination (peer) address */ if (tolen < sizeof(struct Ip_sockaddr_in)) return -IP_ERRNO_EINVAL; in_to = (struct Ip_sockaddr_in*) to; if (in_to->sin_addr.s_addr == IP_INADDR_ANY) return ipnet_sock_unconnect(sock); sock->ip4->daddr_n = in_to->sin_addr.s_addr; sock->dport = ip_ntohs(in_to->sin_port); if (IP_IN_CLASSD(in_to->sin_addr.s_addr)) netif = ipnet_if_indextonetif(sock->vr_index, sock->ip4->multicast_if); src_addr = ipnet_ip4_get_src_addr(sock->vr_index, &in_to->sin_addr, IP_NULL, netif); if (src_addr == IP_NULL) { #ifndef IP_PORT_LKM IPCOM_LOG2(WARNING, "connect failed on socket %d, %s is unreachable", sock->ipcom.fd, ipcom_inet_ntop(IP_AF_INET, &in_to->sin_addr, ipnet->log_buf, sizeof(ipnet->log_buf))); #endif return -IP_ERRNO_EHOSTUNREACH; } if (IP_BIT_ISFALSE(sock->flags, IPNET_SOCKET_FLAG_DONT_REBIND) && IP_BIT_ISSET(sock->flags, IPNET_SOCKET_FLAG_BOUND) && (ipnet_ip4_get_addr_type(sock->ip4->saddr_n, sock->vr_index, IP_NULL) != IPNET_ADDR_TYPE_UNICAST)) { /* * No unicast address specified when the socket was bound, * need to rebind. */ sport = sock->sport; ipnet_sock_unbind(sock); } if (IP_BIT_ISFALSE(sock->flags, IPNET_SOCKET_FLAG_BOUND)) { Ipnet_sock_ops *ops; in_name.sin_family = IP_AF_INET; IPCOM_SA_LEN_SET(&in_name, sizeof(in_name)); in_name.sin_addr.s_addr = src_addr->s_addr; in_name.sin_port = ip_htons(sport); ops = ipnet_sock_get_ops(sock); return ops->bind(sock, (struct Ip_sockaddr *) &in_name, IPCOM_SA_LEN_GET(&in_name), IP_TRUE); } /* else: already bound to an unicast address */ return ipnet_sock_set_reachable(sock); case IP_AF_UNSPEC: return ipnet_sock_unconnect(sock); default: return -IP_ERRNO_EAFNOSUPPORT; } } /* *=========================================================================== * ipnet_sock_ip4_raw_connect *=========================================================================== * Description: Connects a RAW IPv4 socket. * Parameters: sock - The socket to connect. * to - The address to connect to. * tolen - The size of the 'to' buffer. * Returns: 0 = success, <0 = error code * */ IP_STATIC int ipnet_sock_ip4_raw_connect(Ipnet_socket *sock, IP_CONST struct Ip_sockaddr *to, Ip_socklen_t tolen) { int ret; ret = ipnet_sock_ip4_connect(sock, to, tolen); if (ret < 0) return ret; IP_BIT_SET(sock->flags, IPNET_SOCKET_FLAG_CONNECTED); return 0; } /* *=========================================================================== * ipnet_sock_ip4_raw_sendto *=========================================================================== * Description: Transmitts a packet on a raw IPv4 socket. * Parameters: sock - a raw IPv4 socket. * msg - message structure passed to sendmsg() * pkt - packet to transmit * Returns: >=0 = success, magnitude is the number of bytes sent * <0 = error code * */ IP_STATIC int ipnet_sock_ip4_raw_sendto(Ipnet_socket *sock, IP_CONST struct Ip_msghdr *msg, Ipcom_pkt *pkt) { Ipnet_pkt_ip *ip_hdr; int hdr_len; struct Ip_cmsghdr *cmsg; void *rt_lookup_key = IP_NULL; if (IP_BIT_ISFALSE(sock->ip4->flags, IPNET_SOCKET_FLAG_IP4_HDRINCL)) { Ipnet_sock_inet_ops *ops; /* * No IP-header included, use the normal socket transmission * path. */ ops = (Ipnet_sock_inet_ops *) ipnet_sock_get_ops(sock); return ops->network_send(sock, msg, pkt); } #ifdef IPNET_USE_PER_SOCKET_VLAN_TAG if (sock->vlan_tag) { ipnet_vlan_set_tag(pkt, sock->vlan_tag); } #endif /* * The user supplied the IP header */ pkt->ipstart = pkt->start; ip_hdr = ipcom_pkt_get_iphdr(pkt); if (ip_hdr->id == 0) /* * User did not specify a ID, set the next available * one */ ip_hdr->id = (Ip_u16) ipnet->ip4.id++; hdr_len = IPNET_IP4_GET_HDR_OCTET_LEN(ip_hdr); if (hdr_len < IPNET_IP_HDR_SIZE) { ipcom_pkt_free(pkt); return -IP_ERRNO_EINVAL; } /* * Note: strangely enough the IP length is set in host endian! */ ip_hdr->len = (Ip_u16)ip_htons(pkt->end - pkt->ipstart); /* * Use specific interface? */ if (sock->bind_to_ifindex != 0) /* * Bound to a specific device */ pkt->ifindex = sock->bind_to_ifindex; else if (sock->ip4->multicast_if != 0 && IP_IN_CLASSD(IPNET_IP4_GET_IPADDR(ip_hdr->dst))) /* * A specific interface was set with IP_IP_MULTICAST_IF socket * option */ pkt->ifindex = sock->ip4->multicast_if; else pkt->ifindex = 0; if (msg != IP_NULL && msg->msg_controllen > 0) { struct Ip_in_pktinfo *pktinfo = IP_NULL; /* Set extensions header specified to sendmsg() (this overrides any sticky options) */ ip_assert(msg->msg_control != IP_NULL); for (cmsg = IP_CMSG_FIRSTHDR(msg); cmsg != IP_NULL; cmsg = IP_CMSG_NXTHDR(msg, cmsg)) { if (cmsg->cmsg_level != IP_IPPROTO_IP) continue; switch (cmsg->cmsg_type) { case IP_IP_PKTINFO: pktinfo = IP_CMSG_DATA(cmsg); if (pktinfo->ipi_ifindex != 0) pkt->ifindex = pktinfo->ipi_ifindex; break; case IP_IP_X_VRID: IPCOM_PKT_SET_VRID(pkt, *(Ip_u8*) IP_CMSG_DATA(cmsg)); break; } } } IP_BIT_SET(pkt->flags, IPCOM_PKT_FLAG_HAS_IP_HDR); if((msg) && (msg->msg_name) && (IPNET_IP4_GET_IPADDR(ip_hdr->dst) != IP_INADDR_ANY)) { rt_lookup_key = (void*) &((struct Ip_sockaddr_in *)msg->msg_name)->sin_addr; } return ipnet_ip4_pkt_with_iphdr_tx(pkt, rt_lookup_key); } /* *=========================================================================== * ipnet_sock_ip4_bind *=========================================================================== * Description: The IPv4 network layer bind. * Parameters: sock - The socket to bind. * name - The socket name. * namelen - The length of the name variable. * check_reuse - Set to IP_TRUE if the name should be checked * for address reuse. * Returns: 0 = success, <0 = error code * */ IP_STATIC int ipnet_sock_ip4_bind(struct Ipnet_socket_struct *sock, IP_CONST struct Ip_sockaddr *name, Ip_socklen_t namelen, Ip_bool check_reuse) { struct Ip_sockaddr_in *name_in; enum Ipnet_addr_type addr_type = IPNET_ADDR_TYPE_NOT_LOCAL; Ipnet_ip4_addr_entry *addr_entry = IP_NULL; IPCOM_UNUSED_ARG(check_reuse); if (namelen < sizeof(struct Ip_sockaddr_in)) { IPCOM_LOG3(WARNING, "socket %d: namelen too small in bind is %d must be at least %d", sock->ipcom.fd, namelen, sizeof(struct Ip_sockaddr_in)); return -IP_ERRNO_EINVAL; } name_in = (struct Ip_sockaddr_in*)name; /* * Verify that IP address is either ANY (0) or one of my * addresses. Note: it is ok to bind to any multicast address or * the broadcast address. */ if (name_in->sin_addr.s_addr == IP_INADDR_ANY) addr_type = IPNET_ADDR_TYPE_ANY; else if (name_in->sin_addr.s_addr == IP_INADDR_BROADCAST) addr_type = IPNET_ADDR_TYPE_BROADCAST; else if (IP_IN_CLASSD(name_in->sin_addr.s_addr)) addr_type = IPNET_ADDR_TYPE_MULTICAST; else { /* * Check for matching unicast address */ addr_entry = ipnet_ip4_get_addr_entry(name_in->sin_addr.s_addr, sock->vr_index, IP_NULL); if (addr_entry == IP_NULL) { /* * Check all network broadcast addresses */ Ipnet_netif *netif; Ip_u32 i; /* * IPNET_NETIF_FOR_EACH_ON_VR sets netif to NULL after the for loop, * this is a performance optimized defination */ /* coverity[result_independent_of_operands] */ IPNET_NETIF_FOR_EACH_ON_VR(netif, sock->vr_index, i) { addr_entry = ipnet_ip4_get_addr_entry(name_in->sin_addr.s_addr, sock->vr_index, netif); if (addr_entry != IP_NULL) break; } } if (addr_entry != IP_NULL) addr_type = addr_entry->type; } /* * Not my address. */ if (addr_type == IPNET_ADDR_TYPE_NOT_LOCAL) return -IP_ERRNO_EADDRNOTAVAIL; #if defined(IPNET_USE_RFC5227) || defined(IPNET_USE_RFC3927) /* Address still in tentative state, not available */ if ((addr_entry != IP_NULL) && (IP_BIT_ISSET(addr_entry->flags, IPNET_IP4_ADDR_FLAG_TENTATIVE))) return -IP_ERRNO_EADDRNOTAVAIL; #endif if (sock->ipcom.type == IP_SOCK_STREAM && addr_type != IPNET_ADDR_TYPE_UNICAST && addr_type != IPNET_ADDR_TYPE_ANY) { /* * Can't bind stream socket to broadcast/multicast address. */ return -IP_ERRNO_EINVAL; } sock->ip4->saddr_n = name_in->sin_addr.s_addr; #ifndef IPCOM_FORWARDER_NAE /* * SCTP can have many addresses, one is not enough, unbind need * not modify */ if ((addr_entry != IP_NULL) && (IP_IPPROTO_SCTP != sock->proto)) { ip_assert(sock->addr_next == IP_NULL); ip_assert(sock->addr_prev == IP_NULL); /* * Add this socket to list of sockets using the address */ sock->addr_next = addr_entry->socket_list; addr_entry->socket_list = sock; if (sock->addr_next != IP_NULL) sock->addr_next->addr_prev = sock; sock->addr_prev = IP_NULL; sock->addr_entry = addr_entry; } #endif /* !IPCOM_FORWARDER_NAE */ return 0; } /* *=========================================================================== * ipnet_sock_ip4_getname *=========================================================================== * Description: Returns the local name (or address) of the socket. * Parameters: sock - The socket to return the name for. * name - Buffer where the name will be stored. * namelen - The length of the 'name' buffer. * is_local_name - Is set to IP_TRUE of the local name of the * socket should be returned, IP_FALSE means that the peer name * should be returned. * Returns: 0 = success, <0 = error code (-IPNET_ERRNO_xxx) * */ IP_STATIC int ipnet_sock_ip4_getname(struct Ipnet_socket_struct *sock, struct Ip_sockaddr *name, Ip_socklen_t *namelen, Ip_bool is_local_name) { struct Ip_sockaddr_in *name_in; int ret = 0; if (*namelen < sizeof(struct Ip_sockaddr_in)) return -IP_ERRNO_ENOBUFS; *namelen = sizeof(struct Ip_sockaddr_in); name_in = (struct Ip_sockaddr_in *)name; ipcom_memset(name_in->sin_zero, 0, sizeof(name_in->sin_zero)); IPCOM_SA_LEN_SET(name_in, sizeof(struct Ip_sockaddr_in)); name_in->sin_family = IP_AF_INET; if (is_local_name) { name_in->sin_addr.s_addr = sock->ip4->saddr_n; name_in->sin_port = ip_htons(sock->sport); } else { /* * Copy the address before checking if the socket is * connected. TCP may internally call this function when not * connected to get the peer the socket used to be connected * to. */ if (IP_BIT_ISFALSE(sock->flags, IPNET_SOCKET_FLAG_CONNECTED|IPNET_SOCKET_FLAG_CONNECTING)) ret = -IP_ERRNO_ENOTCONN; name_in->sin_addr.s_addr = sock->ip4->daddr_n; name_in->sin_port = ip_htons(sock->dport); } return ret; } /* *=========================================================================== * ipnet_sock_ip4_mcast_remove_source *=========================================================================== * Description: Callback to send a report for every source address * blocked/allowed. * Parameters: source - The source address to remove. * md - The multicast address control block. * Returns: */ #ifdef IPNET_USE_SOURCE_SPECIFIC_MCAST IP_STATIC void ipnet_sock_ip4_mcast_remove_source(struct Ip_in_addr *source, Ipnet_ip4_sock_mcast_data *md) { (void)ipcom_set_remove(md->sources, source); ipnet_igmpv3_report_change(md->netif, &md->maddr); } #endif /* IPNET_USE_SOURCE_SPECIFIC_MCAST */ /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_sock_ip4_get_mcast_data *=========================================================================== * Description: Returns the pointer to where the multicast data for the * specified multicast address is stored. * Parameters: sock - The controlling socket for the multicast address. * netif - The interface the multicast address will be assigned to. * maddr - An multicast address. * Returns: Always != IP_NULL, but the storage might hold IP_NULL which * means that there was not match. */ IP_GLOBAL Ipnet_ip4_sock_mcast_data ** ipnet_sock_ip4_get_mcast_data(Ipnet_socket *sock, Ipnet_netif *netif, IP_CONST struct Ip_in_addr *maddr) { Ipnet_ip4_sock_mcast_data **mlt_it; /* Try to find the multicast address in the socket multicast address list */ for (mlt_it = &sock->ip4->multicast_addr_list; *mlt_it != IP_NULL; mlt_it = &(*mlt_it)->next) { if (maddr->s_addr == (*mlt_it)->maddr.s_addr && netif == (*mlt_it)->netif) break; } return mlt_it; } /* *=========================================================================== * ipnet_sock_ip4_mcast_delete_data *=========================================================================== * Description: Deletes a multicast data block for a specific address. * Parameters: sock - The controlling socket for the multicast address. * netif - The interface the multicast address will removed from. * maddr - An multicast address. * Returns: >=0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_sock_ip4_mcast_delete_data(Ipnet_socket *sock, Ipnet_netif *netif, struct Ip_in_addr *maddr) { Ipnet_ip4_sock_mcast_data *mcast_data; Ipnet_ip4_sock_mcast_data **pmcd; #ifdef IPNET_USE_SOURCE_SPECIFIC_MCAST Ipnet_ip4_addr_entry *addr_entry; int filter_mode; #endif pmcd = ipnet_sock_ip4_get_mcast_data(sock, netif, maddr); mcast_data = *pmcd; if (mcast_data == IP_NULL) /* This address has not been joined */ return -IP_ERRNO_EADDRNOTAVAIL; #ifdef IPNET_USE_SOURCE_SPECIFIC_MCAST /* Send IGMPv3 report if the interface filter changes */ ipcom_set_for_each(mcast_data->sources, (Ipcom_set_foreach_cb_func) ipnet_sock_ip4_mcast_remove_source, mcast_data); filter_mode = mcast_data->sources->user; ipcom_set_delete(mcast_data->sources); addr_entry = ipnet_ip4_get_addr_entry(maddr->s_addr, sock->vr_index, netif); if (addr_entry != IP_NULL) (void)ipcom_set_remove(addr_entry->mcast.sockets, &sock); /* else: This socket does not control this multicast address */ if (filter_mode == IPCOM_SET_IS_EXCLUDE) ipnet_igmpv3_report_change(mcast_data->netif, &mcast_data->maddr); #endif /* IPNET_USE_SOURCE_SPECIFIC_MCAST */ /* Unhook 'mcast_data' from the list */ *pmcd = mcast_data->next; ipcom_free(mcast_data); return ipnet_ip4_remove_addr(netif, maddr->s_addr); } /* *=========================================================================== * ipnet_sock_ip4_lookup *=========================================================================== * Description: Returns the IPv4 socket matching the parameters. * Parameters: vr - The virtual router the socket must be bound to. * proto - The protocol the returned socket should be using. * local_addr_ptr - The IPv4 address in network order of the * local address to match or IP_NULL if any address should match. * local_port - The source port in HOST byte order or 0 if any * source port should match. * peer_addr_n - The IPv4 address in network order of the * peer address to match or IP_NULL if any address should match. * peer_port - The destination port in HOST byte order or 0 if any * destination port should match. * pfirst - [in] the socket descriptor to from where the scan should start * [out] the socket descriptor to start the next search from. * set to IP_NULL to start from 0. * Returns: A pointer to the matching socket or IP_NULL if no socket match. * */ IP_GLOBAL Ipnet_socket * ipnet_sock_ip4_lookup(Ip_u16 vr, int proto, IP_CONST Ip_u32 *local_addr_ptr, Ip_u16 local_port, IP_CONST Ip_u32 *peer_addr_ptr, Ip_u16 peer_port) { Ipnet_socket *sock; Ipnet_socket_lookup_key key; key.domain = IP_AF_INET; key.proto = (Ip_u16) proto; key.vr = vr; key.local_port = local_port; key.peer_port = peer_port; if (local_addr_ptr) key.local_addr.in.s_addr = IP_GET_32ON16(local_addr_ptr); else key.local_addr.in.s_addr = 0; if (peer_addr_ptr) key.peer_addr.in.s_addr = IP_GET_32ON16(peer_addr_ptr); else key.peer_addr.in.s_addr = 0; sock = ipnet_sock_get(&key, IP_NULL); if (sock == IP_NULL) { key.peer_port = 0; key.peer_addr.in.s_addr = 0; sock = ipnet_sock_get(&key, IP_NULL); if (sock == IP_NULL) { Ip_u32 local_addr = key.local_addr.in.s_addr; key.local_addr.in.s_addr = 0; sock = ipnet_sock_get(&key, IP_NULL); /* If MCP is enabled, all multicast packets will be received. */ if (ipmcp_is_enabled == IP_TRUE) return sock; /* For multicast address the socket which has joined the related group could receive the data. */ if (IP_IN_CLASSD(local_addr) && local_addr != ip_htonl(0xe0000001)) { while(sock != IP_NULL && sock->ipcom.type == IP_SOCK_DGRAM) { Ipnet_ip4_sock_mcast_data *mc_addr = sock->ip4->multicast_addr_list; while (mc_addr != IP_NULL) { if (mc_addr->maddr.s_addr == local_addr) return sock; mc_addr = mc_addr->next; } /* search for next socket */ if (mc_addr == IP_NULL) sock = ipnet_sock_next(sock); } } } } #ifdef IPCOM_USE_INET6 if (sock == IP_NULL) { struct Ip_in6_addr local_in6; struct Ip_in6_addr peer_in6; if (local_addr_ptr) key.local_addr.in.s_addr = IP_GET_32ON16(local_addr_ptr); if (peer_addr_ptr) key.peer_addr.in.s_addr = IP_GET_32ON16(peer_addr_ptr); ipnet_ip6_create_mapped_addr(&key.local_addr.in, &local_in6); ipnet_ip6_create_mapped_addr(&key.peer_addr.in, &peer_in6); sock = ipnet_sock_ip6_lookup(vr, proto, &local_in6, local_port, &peer_in6, peer_port); if (sock == IP_NULL || IP_BIT_ISSET(sock->ip6->flags, IPNET_SOCKET_FLAG_IP6_V6ONLY)) return IP_NULL; } #endif /* IPCOM_USE_INET6 */ return sock; } /* *=========================================================================== * ipnet_sock_ip4_get_ops *=========================================================================== * Description: Sets all members that are valid for IPv4. * Parameters: ops - Socket operation structure. * Returns: * */ IP_GLOBAL void ipnet_sock_ip4_get_ops(Ipnet_sock_inet_ops *ops) { ipnet_usr_sock_get_ops(&ops->sock); ops->sock.domain = IP_AF_INET; #ifdef IPIPSEC2 ops->sock.hdr_space = IPNET_IP_HDR_SIZE + IPIPSEC_IPSEC_HDR_MAX_SIZE; #else ops->sock.hdr_space = IPNET_IP_HDR_SIZE; #endif ops->sock.extra_sock_space = sizeof(Ipnet_ip4_socket); ops->sock.init = ipnet_sock_ip4_init; ops->sock.destroy = ipnet_sock_ip4_destroy; ops->sock.bind = ipnet_sock_bind; ops->sock.connect = ipnet_sock_ip4_connect; ops->sock.lookup = (Ipnet_sock_lookup_f) ipnet_sock_ip4_lookup; ops->sock.send = ipnet_ip4_sendto; ops->sock.getname = ipnet_sock_ip4_getname; ops->network_bind = ipnet_sock_ip4_bind; ops->network_send = ipnet_ip4_sendto; } /* *=========================================================================== * ipnet_sock_ip4_register *=========================================================================== * Description: Registers the IP_SOCK_RAW type for the IP_AF_INET domain. * Parameters: * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_sock_ip4_register(void) { Ipnet_sock_inet_ops *ops; ops = ipcom_calloc(1, sizeof(*ops)); if (ops == IP_NULL) { IPCOM_LOG0(CRIT, "Could not register the IP_SOCK_RAW in IP_AF_INET domain, out of memory"); IP_PANIC(); return -IP_ERRNO_ENOMEM; } ipnet_sock_ip4_get_ops(ops); ops->sock.type = IP_SOCK_RAW; ops->sock.proto = -1; ops->sock.connect = ipnet_sock_ip4_raw_connect; ops->sock.send = ipnet_sock_ip4_raw_sendto; ops->sock.extra_sock_space += sizeof(struct Ip_icmp_filter); return ipnet_sock_register_ops(&ops->sock); } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ #endif /* IPCOM_USE_INET */ /* **************************************************************************** * END OF FILE **************************************************************************** */