/* ****************************************************************************** * HEADER FILE * * Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipnet_h.h,v $ $Revision: 1.254.10.32 $ * $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_h.h,v $ * $Author: jren $ $Date: 2020-04-21 02:14:42 $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ #ifndef IPNET_H_H #define IPNET_H_H /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipnet_config.h" #define IPNET_MAX_IF_EVENTCB 8 /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #include "ipnet.h" #include "ipnet_netif.h" #ifdef IPCOM_USE_INET #include "ipnet_ip4.h" #endif #ifdef IPCOM_USE_INET6 #include "ipnet_ip6.h" #endif #ifdef IPIPSEC2 #include #endif #include "ipnet_nat_h.h" #ifdef IPNET_USE_DIFFSERV #include "ipnet_diffserv.h" #include #endif #include "ipnet_route.h" #include "ipnet_signal.h" #include "ipnet_timeout.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef IPCOM_USE_JOB_QUEUE #include #endif #ifdef IPPPP #include #endif #include "ipnet_netlink_h.h" #include "ipnet_rtnetlink_h.h" #ifdef __cplusplus extern "C" { #endif /* **************************************************************************** * 4 DEFINES **************************************************************************** */ #define IPNET_FD_TO_SOCKET_EX(fd, sock, must_be_open) \ if (IP_UNLIKELY(fd < IPNET_SOCKET_STARTFD) \ || IP_UNLIKELY(fd >= ipnet_conf_max_sockets) \ || IP_UNLIKELY(IP_NULL == (sock = ipnet->sockets[fd])) \ || (must_be_open && IP_UNLIKELY(IP_BIT_ISSET(sock->flags, IPNET_SOCKET_FLAG_CLOSED)))) \ { \ IPCOM_WV_MARKER_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, \ 1, 1, IPCOM_WV_NETDEVENT_WARNING, \ ipcom_socket, IPCOM_WV_NETD_NOSOCK, \ IPCOM_WV_IPNET_SOCK_MODULE, IPCOM_WV_NETD_SOCKET); \ IPNET_STATS(sock_ebadf++); \ return IPNET_ERRNO(EBADF); \ } #define IPNET_FD_TO_SOCKET(fd, sock) IPNET_FD_TO_SOCKET_EX(fd, sock, IP_FALSE) #define IPNET_FD_TO_OPEN_SOCKET(fd, sock) IPNET_FD_TO_SOCKET_EX(fd, sock, IP_TRUE) #define IPNET_MAKE_ERRNO(err) -(err) #define IPNET_ERRNO(err) IPNET_MAKE_ERRNO(IP_ERRNO_ ## err) #define IPNET_DATA_SETU16(pkt,off,val16) *(Ip_u16*)(&(pkt)->data[off]) = (Ip_u16)(val16) #define IPNET_TIMEVAL_TO_MSEC(tv) (((Ip_s64) (tv).tv_sec * 1000 + (tv).tv_usec / 1000)) /* * Return a number N that where (size % align == 0) and N >= size * i.e. the smallest size that has the specified alignment * requirements */ #define IPNET_ALIGNED_SIZE(size, align) (((size) + (align) - 1) & ~((align) - 1)) /* * This flag is set when the packet contains urgent data. The flag is * used to pass information about MSG_OOB being set in * send()/sendto()/sendmsg() while the packet is being transmitted * through the stack command pipe. */ #define IPNET_PKT_FLAG_URGENT IPCOM_PKT_FLAG_LINK2 /* * Store the offset to the urgent data and mark the packet as urgent */ #define IPNET_MARK_PKT_AS_URGENT(pkt) \ do { \ ipcom_pkt_set_int(pkt, IPNET_PKT_INFO_URGENT_OFFSET, (pkt)->end - (pkt)->start - 1, Ip_u16); \ IP_BIT_SET((pkt)->flags, IPNET_PKT_FLAG_URGENT); \ } while (0) #ifdef IPCOM_FORWARDER_NAE /* * Each NAE is a single thread, so it does not have to lock against * itself. However, the data lock is used for data that is located in * shared memory when using NAE:s so the data must be protected from * access by multiple NAE:s */ #define IPNET_DATA_LOCK(lock) ipcom_enter_critical_region() #define IPNET_DATA_UNLOCK(lock) ipcom_exit_critical_region() #else #define IPNET_DATA_LOCK(lock) ipcom_spinlock_lock(&lock) #define IPNET_DATA_UNLOCK(lock) ipcom_spinlock_unlock(&lock) #endif #define ipnet_copy_to_user(s1,s2,n) ipcom_copy_to_user(s1,s2,n) #define ipnet_copy_from_user(s1,s2,n) ipcom_copy_from_user(s1,s2,n) #define ipnet_in_checksum_memcpy(s1,s2,n) ipcom_in_checksum_memcpy(s1,s2,n) /* *=========================================================================== * IPNET show functions *=========================================================================== */ #if defined(IP_DEBUG) || defined(IPCOM_FORWARDER_NAE) #define IPNET_USE_SHOW #endif /* *=========================================================================== * IPNET privilege *=========================================================================== */ #define IPNET_PRIV_CHVR 1 /* Use has privilege to change the current virtual router */ /* *=========================================================================== * routing socket optional code *=========================================================================== */ #ifdef IPNET_USE_ROUTESOCK #define IPNET_ROUTESOCK(x) x #else #define IPNET_ROUTESOCK(x) IP_NOOP #endif /* *=========================================================================== * netlink socket optional code *=========================================================================== */ #ifdef IPNET_USE_NETLINK #define IPNET_NETLINKSOCK(x) x #else #define IPNET_NETLINKSOCK(x) IP_NOOP #endif #define IPNET_NETLINK_DEF_BUF_SZ 8192 #define IPNET_NETLINK_EXTRA_PAD 50 /* *=========================================================================== * DEBUG/ASSERT *=========================================================================== */ #ifdef IPNET_DEBUG /* #define IPNET_DEBUG_PRINTF -- Now handled per-file */ #define IPNET_DEBUG_LINE(x) x #else #define IPNET_DEBUG_LINE(x) IP_NOOP #endif /* IPNET_DEBUG */ /* *=========================================================================== * pkt id *=========================================================================== */ #if defined(IPNET_DEBUG) || defined(IPNET_ASSERT) #define IPNET_MEM_BEGIN_PAD 0xA110CA7E #define IPNET_MEM_END_PAD 0x12DADE34 #endif /* IPNET_DEBUG */ /* *=========================================================================== * syslog *=========================================================================== */ #ifdef IPCOM_SYSLOG_PRIORITY #undef IPCOM_SYSLOG_PRIORITY #endif #define IPCOM_SYSLOG_PRIORITY IPNET_SYSLOG_PRIORITY #ifdef IPCOM_SYSLOG_FACILITY #undef IPCOM_SYSLOG_FACILITY #endif #define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPNET /* *=========================================================================== * IPNET event semaphore *=========================================================================== */ /* Select stack daemon configuration */ #ifdef IPCOM_STACKD_POST_IMPL /* *=========================================================================== * IPCOM_STACKD_POST_IMPL *=========================================================================== * Description: Notifies the external stack daemon that a stack event * has occured. * Parameters: new_timeout - IP_TRUE if called because a new timeout * has occured. * is_posted - IP_TRUE if this function returned IP_TRUE * the last call and ipcom_stackd_event() has not * since the last call. * Returns: IP_TRUE if 'is_posted' should be IP_TRUE in the next * call if this function is called more times * from the same ipcom_stackd_event() run. * */ IP_EXTERN Ip_bool IPCOM_STACKD_POST_IMPL(Ip_bool new_timeout, Ip_bool is_posted); #define IPCOM_STACKD_POST(new_timeout) \ ipnet->task_posted = IPCOM_STACKD_POST_IMPL(new_timeout, ipnet->task_posted) #else /* !IPCOM_STACKD_POST_IMPL */ #ifdef IPCOM_USE_JOB_QUEUE #define IPCOM_STACKD_POST(new_timeout) #else /* The built-in daemon process is used */ #define IPCOM_STACKD_POST(new_timeout) \ if (!ipnet->task.wakeup_pending) \ { \ ipnet->task.wakeup_pending = IP_TRUE; \ ipcom_pipe_try_send(ipnet->task.pipe, ipnet->task.wakeup_sig); \ } #endif /* IPCOM_USE_JOB_QUEUE */ #endif /* IPCOM_STACKD_POST_IMPL */ /* * Adjust the checksum to reflect that the TTL had been decremented. * * Flip the bits on the checksum, decrement the high byte of the * checksum, fold in any carry, and then flip the bits back. Rather * than convert the checksum to host byte order and then back to * network byte order, just convert the increment to network byte * order. Note: in 1's complement arithmetic, subtracting by x is the * same as adding the 1's complement of x. So, in 16 bit arithmetic, * rather than subtracting by (1<<8), we can add by (1<<8)^0xffff. * Since it's all constants, that should be evaluated by the compiler * at compile time. * * Doing the ^0xffff to initially flip the bits keeps the upper bits * from also being flipped. Using the ~ operation at the end doesn't * matter, because the upper bits get tossed when we assign it to the * 16 bit sum field, so let the compiler do whatever is fastest. */ #define IP_INCREMENTAL_CHECKSUM(ip_hdr) \ do { \ int chksum; \ /* Calculate the incremental checksum update */ \ --ip_hdr->ttl; \ /* increment checksum high byte */ \ chksum = (int)(ip_hdr->sum ^ 0xFFFF) + \ (int)ip_htons((1<<8) ^ 0xFFFF); \ /* Fold the carry bit into the checksum */ \ ip_hdr->sum = (Ip_u16) ~(chksum + (chksum >> 16)); \ } while((0)) /* *=========================================================================== * WindView *=========================================================================== */ #ifdef IPCOM_WV_INSTRUMENTATION #define IPCOM_WV_MARKER_1(classId, eventLevel, eventOffset, eventTag, eventId, arg1, module, entity) \ ipcom_wv_marker_1(classId, eventLevel, eventOffset, eventTag, eventId, arg1, module, entity) #define IPCOM_WV_MARKER_2(classId, eventLevel, eventOffset, eventTag, eventId, arg1, arg2, module, entity) \ ipcom_wv_marker_2(classId, eventLevel, eventOffset, eventTag, eventId, arg1, arg2, module, entity) #define IPCOM_WV_EVENT_2(classId, eventLevel, eventOffset, eventTag, eventId, status, arg1, arg2, module, entity) \ ipcom_wv_event_2(classId, eventLevel, eventOffset, eventTag, eventId, status, arg1, arg2, module, entity) #define IPCOM_WV_VAR1 wv_what #define IPCOM_WV_VAR2 wv_tag #define IPCOM_WV_DECLARE_VARS int IPCOM_WV_VAR1=0, IPCOM_WV_VAR2=0 #define IPCOM_WV_SET_VARS(eventTag, what) do { wv_what = what; wv_tag = eventTag; } while(0) #else #define IPCOM_WV_MARKER_1(classId, eventLevel, eventOffset, eventTag, eventId, arg1, module, entity) \ do {} while (0) #define IPCOM_WV_MARKER_2(classId, eventLevel, eventOffset, eventTag, eventId, arg1, arg2, module, entity) \ do {} while (0) #define IPCOM_WV_EVENT_2(classId, eventLevel, eventOffset, eventTag, eventId, status, arg1, arg2, module, entity) \ do {} while (0) #define IPCOM_WV_VAR1 #define IPCOM_WV_VAR2 #define IPCOM_WV_DECLARE_VARS #define IPCOM_WV_SET_VARS(eventTag, what) #endif /* #ifdef IPCOM_WV_INSTRUMENTATION */ /* IPNET packet information types */ #define IPNET_PKT_INFO_SIG 64 /* Ipnet_sig */ #define IPNET_PKT_INFO_SOCK_SND_BUF 65 /* Ipnet_pkt_info_sock_snd_buf */ #define IPNET_PKT_INFO_URGENT_OFFSET 66 /* Ip_u16 */ #define IPNET_PKT_INFO_TUNNEL_IPSTART 67 /* int */ #define IPNET_PKT_INFO_NETEMU_SEQ_NUM 68 /* Ip_u32 */ #define IPNET_PKT_INFO_DPAF_PQ_INDEX 69 /* unsigned */ #define IPNET_PKT_INFO_TIMEOUT 70 /* Ip_u32 */ #define IPNET_PKT_INFO_PEER_INFO_PTR 71 /* Ipnet_peer_info* */ #define IPNET_PKT_INFO_IPSEC_CATEGORY 72 /* int */ #define IPNET_PKT_INFO_ZONE_ID 73 /* Ip_u32 */ #define IPNET_PKT_INFO_L4_CHKSUM_PTR 74 /* void* */ #define IPNET_PKT_INFO_ENCAP_UDP (75 | IPCOM_PKT_INFO_COPY) /* 8 bytes */ #define IPNET_PKT_INFO_ENCAP (76 | IPCOM_PKT_INFO_COPY) /* 4 bytes */ #define IPNET_PKT_INFO_GRE_KEY_OUTPUT (77 | IPCOM_PKT_INFO_COPY) /* Ip_u32 */ #define IPNET_PKT_INFO_SEND_SIG_VERIFIED (78 | IPCOM_PKT_INFO_COPY) /* void */ #define IPNET_PKT_INFO_DSTOPT_HOA (79 | IPCOM_PKT_INFO_COPY)/* struct Ip_in6_addr* */ #define IPNET_PKT_INFO_RTHDR2 (80 | IPCOM_PKT_INFO_COPY)/* struct Ip_in6_addr* */ #define IPNET_PKT_INFO_CLONEDPKT 81 /* struct Ipcom_pkt* */ #define IPNET_PKT_INFO_INGRESS_IFINDEX 82 /* unsigned */ #define IPNET_PKT_INFO_ENCAP_FLAGS_SET(v, p) (((v) << 8) | (p)) #define IPNET_PKT_INFO_ENCAP_FLAGS_GET_PROTO(f) ((f) & 0xFF) #define IPNET_PKT_INFO_ENCAP_FLAGS_GET_VER(f) (((v) >> 8) & 0xFF) #define IPNET_PKT_INFO_FLAGS_GET_SIZE(f) (((f) >> 24) & 0xFF) #define IPCOM_INET6_MASK_LEN 16 #define IPCOM_INET_MASK_LEN 4 /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* Forward declaration */ struct Ipnet_netif_struct; struct Ipnet_peer_info_struct; /* *=========================================================================== * Ipnet_pkt_udp *=========================================================================== */ #include "ipcom_align16.h" typedef IP_PACKED1 struct Ipnet_pkt_udp_struct { Ip_u16 sport; /* Source port. */ Ip_u16 dport; /* Destination port. */ Ip_u16 ulen; /* UDP length. */ Ip_u16 sum; /* UDP checksum. */ } IP_PACKED2 Ipnet_pkt_udp; #define IPNET_UDP_HDR_SIZE (8) /* UDP header is 8 octets long */ /* * RFC 3828 UDP-Lite packet */ typedef IP_PACKED1 struct Ipnet_pkt_udplite_struct { Ip_u16 sport; /* Source port. */ Ip_u16 dport; /* Destination port. */ Ip_u16 sum_cov; /* Octes covered by the checksum */ Ip_u16 sum; /* UDP-Lite checksum. */ } IP_PACKED2 Ipnet_pkt_udplite; #define IPNET_UDPLITE_HDR_SIZE (8) /* UDP header is 8 octets long */ /* *=========================================================================== * Ipnet_frame *=========================================================================== */ typedef IP_PACKED1 union Ipnet_pkt_union_union { #ifdef IPCOM_USE_INET Ipnet_pkt_icmp icmp; #endif Ipnet_pkt_udp udp; } IP_PACKED2 IP_Ipnet_pkt_union; #include "ipcom_align16.h" /* * Packet information describing how much of the socket send buffer * this packet occupies */ typedef struct Ipnet_pkt_info_sock_snd_buf_struct { /* * Pointer to the socket used to sent this packet. Direct pointer * is OK since the socket will not be freed until the send buffer * is ==0 */ struct Ipnet_socket_struct *sock; /* * Number of bytes this packet has reserved in the send buffer. Is * always >0 */ int payload_len; } Ipnet_pkt_info_sock_snd_buf; /* *=========================================================================== * Ipnet_sock_init_f *=========================================================================== * Description: Called last in the socket creation and can proviced custom * initialization of the socket. * Parameters: sock - The affected socket. * user_context - IP_TRUE if called in the context of a user process * IP_FALSE if called in the context of the kernel. * Returns: 0 = success, <0 = error code (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_sock_init_f)(struct Ipnet_socket_struct *sock, Ip_bool user_context); /* *=========================================================================== * Ipnet_sock_destroy_f *=========================================================================== * Description: Called when the socket is going to be deleted. * Can contain domain specific cleanups. * Parameters: sock - The affected socket. * Returns: * */ typedef void (*Ipnet_sock_destroy_f)(struct Ipnet_socket_struct *sock); /* *=========================================================================== * Ipnet_sock_close_f *=========================================================================== * Description: Called when the socket is beeing closed. Should be defined * if special handling, not done by shutdown(sock, IP_SHUT_RDWR), * is required. * Parameters: sock - The affected socket. * Returns: 0 = success, <0 = error code (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_sock_close_f)(struct Ipnet_socket_struct *sock); /* *=========================================================================== * Ipnet_sock_lookup_f *=========================================================================== * Description: Returns the first socket that matches the specified parameters. * Parameters: vr - The virtual route table the socket must match. * proto - the protocol to match. * local_addr - the local address to match or IP_NULL for any address. * local_port - the local port to match or 0 for any port. * peer_addr - the peer address to match or IP_NULL for any address. * peer_port - the peer port to match or 0 for any port. * first - [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: The matching socket or IP_NULL if no socket (from [*first..sock_max] * matched. * */ typedef struct Ipnet_socket_struct * (*Ipnet_sock_lookup_f)(Ip_u16 vr, int proto, IP_CONST void *local_addr, Ip_u16 local_port, IP_CONST void *peer_addr, Ip_u16 peer_port); /* *=========================================================================== * Ipnet_sock_send_f *=========================================================================== * Description: Send handler for the domain/type/protocol tuple * Parameters: sock - The socket the packet beeing sent on. * msg - Message structure with (unconnected sockets) destination * address and (optional) auxillary data. Can be IP_NULL * if the socket is connected and no auxillary data is * needed. 'msg_flags' contains the flags passed * in the 'flags' field to ipcom_sendmsg(). * * pkt - The * Returns: 0 = success, <0 = error code (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_sock_send_f)(struct Ipnet_socket_struct *sock, IP_CONST struct Ip_msghdr *msg, Ipcom_pkt *pkt); /* *=========================================================================== * Ipnet_sock_bind_f *=========================================================================== * Description: Binds a socket. * Parameters: sock - The socket to bind. * name - The socket name. * namelen - The length of the name variable. * user_context - IP_TRUE if called in the context of a user process * IP_FALSE if called in the context of the kernel. * Returns: 0 = success, <0 = error code (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_sock_bind_f)(struct Ipnet_socket_struct *sock, IP_CONST struct Ip_sockaddr *name, Ip_socklen_t namelen, Ip_bool user_context); /* *=========================================================================== * Ipnet_sock_connect_f *=========================================================================== * Description: Binds a socket. * 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 (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_sock_connect_f)(struct Ipnet_socket_struct *sock, IP_CONST struct Ip_sockaddr *to, Ip_socklen_t tolen); /* *=========================================================================== * Ipnet_sock_shutdown_f *=========================================================================== * Description: Shutdown read and/or write end of the socket, IPNET * takes care of flagging the socket read/write end as shut, * and notifies blocked sockets. Protocol specific things has * to be done in this handler though (like sending FIN for TCP). * Parameters: sock - The socket to shutdown. * how - IP_SHUT_xxx constant. * Returns: * */ typedef void (*Ipnet_sock_shutdown_f)(struct Ipnet_socket_struct *sock, int how); /* *=========================================================================== * Ipnet_sock_accept_f *=========================================================================== * Description: Accepts a socket. * Parameters: sock - The socket to bind. * name - The address of the accepted socket. * namelen - The length of the name variable. * Returns: >=0 = success (file descripto), <0 = error code (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_sock_accept_f)(struct Ipnet_socket_struct *sock, struct Ip_sockaddr *name, Ip_socklen_t *namelen); /* *=========================================================================== * Ipnet_sock_listen_f *=========================================================================== * Description: Puts a socket in listen mode. * Parameters: sock - The socket to put in listen mode. * backlog - The size of the socket backlog. * Returns: 0 = success, <0 = error code (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_sock_listen_f)(struct Ipnet_socket_struct *sock, int backlog); /* *=========================================================================== * Ipnet_sock_setopt_f *=========================================================================== * Description: Handles socket option. * Parameters: sock - The socket to set an option on. * level - The protocol level that should be affected by the * option. * optname - The option name. * optval - Data to set for the option. * optlen - The length of the buffer pointed to by optval. * Returns: 0 = success, * -IP_ERRNO_EOPNOTSUPP = This handler does not implement this option, * try other handlers * <0 = error code (-IPNET_ERRNO_xxx), do not try other handlers * */ typedef int (*Ipnet_sock_setopt_f)(struct Ipnet_socket_struct *sock, int level, int optname, IP_CONST void *optval, Ip_socklen_t optlen); /* *=========================================================================== * Ipnet_sock_getopt_f *=========================================================================== * Description: Handles socket option. * Parameters: sock - The socket to get an option from. * level - The protocol level that should be affected by the * option. * optname - The option name. * optval - Data to set for the option. * optlen - The length of 'optval' when calling, * number of bytes copied to 'optval' when returning. * Returns: 0 = success, * -IP_ERRNO_EOPNOTSUPP = This handler does not implement this option, * try other handlers * <0 = error code (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_sock_getopt_f)(struct Ipnet_socket_struct *sock, int level, int optname, void *optval, Ip_socklen_t *optlen); /* *=========================================================================== * Ipnet_sock_getname_f *=========================================================================== * 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) * */ typedef int (*Ipnet_sock_getname_f)(struct Ipnet_socket_struct *sock, struct Ip_sockaddr *name, Ip_socklen_t *namelen, Ip_bool is_local_name); /* *=========================================================================== * Ipnet_sock_ioctl_f *=========================================================================== * Description: Handles IO control on the socket. * Parameters: sock - The socket to get an option from. * request - The IO control request. * argp - Request specific data. * Returns: 0 = success, * <0 = error code (-IPNET_ERRNO_xxx) * -IP_ERRNO_EOPNOTSUPP = This handler does not implement this option, * try other handlers * */ typedef int (*Ipnet_sock_ioctl_f)(struct Ipnet_socket_struct *sock, unsigned long request, void *argp); /* *=========================================================================== * Ipnet_usr_sock_recv_f *=========================================================================== * Description: Called in context of the receiving task. Proper * locking must be done by the this function to * safely extract the data from the socket. * Parameters: sock - The socket to receive from. * msg - 'msg_iov' contains the buffer(s) to where the * received data should be copied. * flags - IP_MSG_xxx flags. * Returns: 0 = success, <0 = error code (-IPNET_ERRNO_xxx) * */ typedef int (*Ipnet_usr_sock_recv_f)(struct Ipnet_socket_struct *sock, struct Ip_msghdr *msg, int flags); typedef struct Ipnet_pkt_result_struct { Ipcom_pkt * pkt; /* * The transient_err will generally be 0 for datagram sockets. * However, for stream sockets, short writes may be possible if the * Ipnet_usr_sock_pkts_from_iov_f function is interrupted by * a signal or a deletion attempt. */ int transient_err; /* 0 or IP_ERRNO_EINTR or IP_ERRNO_EDOOM */ } Ipnet_pkt_result; /* *=========================================================================== * Ipnet_usr_sock_pkts_from_iov_f *=========================================================================== * Description: Called in context of the sending task. Proper * locking must be done by the this function if * members of the socket are read or modified. * Parameters: sock - The socket that will be use to send. * msg - 'msg_iov' contains the buffer(s) to send. * flags - IP_MSG_xxx flags. * offset - Number of bytes into the msg->msg_iov buffers * where the copy into packets should start. * total_buf_len - the sum of the length of all * msg->msg_iov buffers in 'msg'. * prslt - Points to result structure where the constructed packet * and transient error (if any) are returned. * prslt->pkt->next points to the next packet in case * more than one packet was allocated. * Returns: <0 = error code (-IPNET_ERRNO_xxx) * 0 = this operation released the socket lock, the * sendmsg operation must be restarted * >0 = number of bytes that have been allocated in the * socket send buffer and copied into the * packet(s) pointed to by prslt->pkt. * */ typedef int (*Ipnet_usr_sock_pkts_from_iov_f)(struct Ipnet_socket_struct *sock, IP_CONST struct Ip_msghdr *msg, int flags, int offset, int total_buf_len, Ipnet_pkt_result *prslt); /* * Socket operations for a domain/type/proto tuple, functions can be * left as IP_NULL if that operation is not supported */ typedef struct Ipnet_sock_ops_struct { int domain; /* The domain this operations is valid for */ int type; /* The socket type operations is valid for */ int proto; /* The protocol or -1 for any protocol */ Ip_size_t extra_sock_space; /* Extra space to be allocated at the end of the socket */ Ip_size_t hdr_space; /* Minimum header space needed at by the domain/type/proto */ Ip_bool allow_async_send; /* IP_TRUE if this socket type allows asynchronous send */ Ipnet_sock_accept_f accept; Ipnet_sock_bind_f bind; Ipnet_sock_close_f close; Ipnet_sock_connect_f connect; Ipnet_sock_destroy_f destroy; Ipnet_sock_getname_f getname; Ipnet_sock_getopt_f getopt; Ipnet_sock_init_f init; Ipnet_sock_ioctl_f ioctl; Ipnet_sock_listen_f listen; Ipnet_sock_lookup_f lookup; Ipnet_sock_send_f send; Ipnet_sock_setopt_f setopt; Ipnet_sock_shutdown_f shutdown; Ipnet_usr_sock_recv_f usr_recv; Ipnet_usr_sock_pkts_from_iov_f pkts_from_iov; } Ipnet_sock_ops; /* * Internal socket structure used by IPNET to implement IP_AF_INET and * IP_AF_INET 6 */ typedef struct Ipnet_sock_inet_ops_struct { Ipnet_sock_ops sock; Ipnet_sock_bind_f network_bind; Ipnet_sock_send_f network_send; } Ipnet_sock_inet_ops; /* *=========================================================================== * Ipnet_dynhdrspc *=========================================================================== * Description: Returns the number of octets that must be allocated to fit * IP options and/or extension headers. * Parameters: sock - The socket used to send the datagram. * msg - The message data passed to ipcom_sendmsg(). * Returns: Number of extra octets that must be allocated. * */ typedef Ip_size_t (*Ipnet_dynhdrspc)(struct Ipnet_socket_struct *sock, IP_CONST struct Ip_msghdr *msg); /* *=========================================================================== * Ipnet_is_sock_ready_cb *=========================================================================== * Description: Callback that will determine if the specified socket * is ready or not. * Parameters: sock - a socket. * lowat - minimum number of bytes that has to be * available in the send/receive buffer in order to * consider the socket to be writable/readable. 0 * means that the socket default value should be used. * Returns: IP_TRUE if the socket is ready. * */ typedef Ip_bool (*Ipnet_is_sock_ready_cb)(struct Ipnet_socket_struct *sock, int lowat); /* *=========================================================================== * Ipnet_transport_layer_rx_func *=========================================================================== * Description: Handler for a specific IPv4/IPv6 payload protcol. The packet * ownership is transfered to the handler. * Parameters: dst - destination cache for the flow used by the packet. * pkt - packat that is being delivered * Returns: * */ typedef void (*Ipnet_transport_layer_rx_func)(struct Ipnet_dst_cache_struct *dst, Ipcom_pkt *pkt); #ifdef IPCOM_FORWARDER_NAE /* *=========================================================================== * Ipnet_sock_nae_rx_func *=========================================================================== * Description: Handler for reception on a specific * socket. Applications running within a NAE would * use this to get notification. * Parameters: fd - socket matching the received packet. * pkt - the received packet. * ctx - user defined context data. * Returns: * */ typedef void (*Ipnet_sock_nae_rx_func)(int fd, Ipcom_pkt *pkt, void *ctx); #endif #ifdef IPCOM_ATOMIC_TAG_VIA_SPINLOCK #define ipcom_nae_socket_atomic(sock) ipcom_nae_switch_to_lock(&sock->nae_lock) #define ipcom_nae_socket_ordered(sock) ipcom_nae_switch_to_null() #define ipcom_nae_socket_is_atomic(sock) ipcom_nae_is_locked(&sock->nae_lock) #else #define ipcom_nae_socket_atomic(sock) ipcom_nae_switch_to_atomic(sock->atomic_tag) #define ipcom_nae_socket_ordered(sock) ipcom_nae_switch_to_ordered(sock->atomic_tag) #define ipcom_nae_socket_is_atomic(sock) ipcom_nae_is_atomic(sock->atomic_tag) #endif /* *=========================================================================== * Ipnet_socket *=========================================================================== */ typedef struct Ipnet_socket_struct { Ipcom_socket ipcom; /* Generic socket parameters */ Ipcom_atomic_t ref_count; /* Socket reference count */ Ip_u32 flags; /* Socket flags. */ int ops_handle; /* Handle for the socket operations for this socket */ void *signal; #ifdef IPCOM_FORWARDER_NAE #ifdef IPCOM_ATOMIC_TAG_VIA_SPINLOCK Ipcom_ipc_spinlock_t nae_lock; #else /* * The tag parameter to use in ipcom_switch_to_atomic() before any * member of this structure can be accessed. */ unsigned atomic_tag; #endif /* * User specific data that will be passed verbatim to the * nae_rx_action/nae_rx_notifier function. * NOTE: must point to memory that is accessable by all NAE:s, * i.e. shared memory. */ void *nae_action_ctx; /* * Must take care of the packet, it will not be queued on the * socket if this handler is set. The 'nae_rx_action' contains * the name of the function. The action handler is called via * ipnet_sock_rx_action() which will locate the function with * that name and store the address in the 'nae_rx_action_funcs' * array. The NAE instance number is used as index in the array. */ char *nae_rx_action; Ipnet_sock_nae_rx_func nae_rx_action_funcs[IPCOM_MAX_NAE]; /* * Is called when the a new packet has been queued on the * socket. The 'nae_rx_notifier' contains the name of the * function. The action handler is called via * ipnet_sock_rx_notifier() which will locate the function with * that name and store the address in the 'nae_rx_notifier_funcs' * array. The NAE instance number is used as index in the array. */ char *nae_rx_notifier; Ipnet_sock_nae_rx_func nae_rx_notifier_funcs[IPCOM_MAX_NAE]; /* * Action handler that TCP/SCTP listen socket will assign to all * child sockets spawned from it. */ char *nae_rx_child_action; #else /* * Address removal notifications cannot be used in a NAE since the * address structures are per-NAE and the sockets are shared * between NAE:s. */ struct Ipnet_socket_struct *addr_prev; /* Previous socket bound to the same address */ struct Ipnet_socket_struct *addr_next; /* Next socket bound to the same address */ void *addr_entry; /* Pointer to the address entry for the bind address */ #endif /* IPCOM_FORWARDER_NAE */ /* * List of reachable sockets hashing to the same * ipnet->reachable_sockets bucket. */ Ipcom_list reachable_list; /* * Points to the first socket in the 'ipnet->reachable_sockets' * bucket that share the same socket lookup tuple. This pointer is * IP_NULL if this is the only socket with a specific tuple. */ struct Ipnet_socket_struct *first_sibling; Ip_u16 proto; /* Protocol */ Ip_u16 vr_index; /* The virtual router to use when sending/receiving packets on this socket */ Ip_u16 max_hdrspace; /* Maximum needed header space for network (IP) and transport layer. */ Ip_u16 chk_offset; /* Offset into the transport layer (TCP, UDP, e.t.c) where the 16 bit internet checksum should be stored, used if the flag IPNET_SOCKET_FLAG_ADDCHECKSUM is set */ Ip_u16 sport; /* Source port. */ Ip_u16 dport; /* Destination port. */ struct Ip_sockaddr_storage last_to; /* Address of the node to which something was last sent on this socket */ Ip_u16 biggest_msg_size_in_sync; /* The biggest successfully send msg size in using synchronous mode */ Ip_u8 large_send_countdown; /* The count of successfully sending large msg on this socket. If it is 0, must use synchronous send. */ #ifdef IPNET_USE_PER_SOCKET_VLAN_TAG Ip_u16 vlan_tag; /* Bit 0-2 is priority, bit 3 is priority tagging on/off bit 4-15 is the VLAN tag */ #endif Ip_u16 udplite_sum_cov; /* Number of bytes covered by the RFC3828 UDP-Lite checksum. Must be 0 (all bytes), or >=8 */ Ip_u8 uni_hop_limit; /* The hop limit for unicast packtes */ Ip_u8 multi_hop_limit; /* The hop limit for multicast packtes */ Ip_u8 promisc_count; /* Number of times promisc mode has been entered on this socket */ Ip_u8 udp_encapsulation; /* UDP encapsulation method */ Ip_u32 bind_to_ifindex; /* The interface this socket is bound to (with IP_SO_BINDTODEVICE). ==0 -> not bound */ #ifdef IPNET_USE_RFC2890 Ip_u32 gre_key; /* GRE key for this socket */ #endif int keep_alive_probe_delay; /* Number of seconds an TCP connection must be idle before the first keep-alive probe is sent */ Ipcom_pkt_dtor pkt_dtor; /* Packet destruction that most be used for packets sent using this socket */ Ipnet_dynhdrspc dynamic_header_space; int send_max_bytes; /* Max number of bytes that can be stored in the send buffer */ int recv_max_bytes; /* Max number of bytes that can be stored in the recieve buffer */ int snd_route_cache_id; /* Value of ipnet->route_cache_id at last successful send */ Ipcom_atomic_t snd_bytes; /* Bytes in send buffer */ Ipcom_atomic_t waiting_writers; /* Number of waiting writers on this socket */ Ipcom_pkt *snd_head; /* Output queue, only used if IP_MSG_MORE flag is used */ struct Ip_sockaddr *snd_to; /* Cached to address specified in a sendmsg() with IP_MSG_MORE */ /* * Variables used by protocols that is datagram based, the TCP * receive queue is found in 'tcb' */ Ipcom_spinlock rcv_lock; /* Must be locked when modifying rcv_head, rcv_tail and ipcom.rcv_bytes */ Ipcom_pkt *rcv_head; /* Input packet queue head, pkt->start is the offset to the transport layer header. */ Ipcom_pkt *rcv_tail; /* Input packet queue tail. */ /* * Synchronization objects used when receiving data */ struct Ip_timeval *rcv_timeout; /* Time that a blocking ipcom_recv can bloc, IP_NULL means infinite time */ #ifdef IPNET_USE_SO_CONNTIMEO struct Ip_timeval *conn_timeout; /* Time that for connectWithTimeout */ #endif /* * List of struct Ipnet_sig_poll instances added by task(s) that * are waiting for the socket to become readable, writable and/or * exceptional */ Ipcom_list poll_list_head; #ifdef IPTCP struct Iptcp_tcb_struct *tcb; /* Transmission control block (used by TCP) */ void (*notify_cb)(struct Ipnet_socket_struct *sock, int event); /* See Iptcp_notifycb in iptcp.h */ #endif #ifdef IPSCTP struct Ipsctp_instance_struct *sctp_inst; /* Transmission control block (used by SCTP) */ #endif #if defined(IP_PORT_VXWORKS) && defined(IPCOM_USE_SOCK_COMPAT) void *select_ctx; #ifdef IPNET_SO_WAKEUP_HOOK void *windnet_so; #endif #endif void *sock_end; /* The current end of the socket, used to set up layer specific space */ Ip_u32 timestamp_flag; /* Socket timestamp flag. */ #ifdef IPCOM_USE_INET Ipnet_ip4_socket *ip4; #endif #ifdef IPCOM_USE_INET6 Ipnet_ip6_socket *ip6; #endif #ifdef IPCOM_USE_PACKET Ipnet_packet_socket *ps; #endif #ifdef IPNET_USE_NETLINKSOCK Ipnet_netlink_socket *nl; #endif /* !NOTE! do not put any struct members below this point */ } Ipnet_socket; /* socket flags. */ /* Flags controlled by socket options */ #define IPNET_SOCKET_FLAG_REUSEADDR (1u << 0) /* Resuse of address is ok */ #define IPNET_SOCKET_FLAG_REUSEPORT (1u << 1) /* Resuse of port and address is ok */ #define IPNET_SOCKET_FLAG_DONTROUTE (1u << 2) /* Bypass routing for outgoing messages */ #define IPNET_SOCKET_FLAG_LOOP_MULTICAST (1u << 3) /* Loopback multicast packets sent from this host */ #define IPNET_SOCKET_FLAG_TCP_NODELAY (1u << 4) /* Nagle algorithm is OFF when this flag is set */ #define IPNET_SOCKET_FLAG_RECV_IF (1u << 5) /* Returns the recv if for datagram proto */ #define IPNET_SOCKET_FLAG_RECVPKTINFO (1u << 6) /* Returns extra information about received packets */ #define IPNET_SOCKET_FLAG_KEEPALIVE (1u << 7) /* Probe idle connection */ #define IPNET_SOCKET_FLAG_NONBLOCKING (1u << 8) /* Socket is in non-blocking mode */ #define IPNET_SOCKET_FLAG_ADDCHECKSUM (1u << 9) /* Pseudo header checksum should be added to outgoing packets */ #define IPNET_SOCKET_FLAG_OOBINLINE (1u << 10) /* Out-of-band data should be mixed with normal data */ #define IPNET_SOCKET_FLAG_SENDER_LINK_ADDR (1u << 11) /* Get link address of sender */ /* Socket long term state */ #define IPNET_SOCKET_FLAG_REACHABLE (1u << 12) /* Set if the socket can match incoming packets */ #define IPNET_SOCKET_FLAG_BOUND (1u << 13) /* Socket is bound (explicit or implicit) */ #define IPNET_SOCKET_FLAG_CONNECTING (1u << 14) /* Asynchronous connect in progress */ #define IPNET_SOCKET_FLAG_CONNECTED (1u << 15) /* Socket is connected */ #define IPNET_SOCKET_FLAG_READ_CLOSED (1u << 16) /* The read end of the socket is closed */ #define IPNET_SOCKET_FLAG_WRITE_CLOSED (1u << 17) /* The write end of the socket is closed */ #define IPNET_SOCKET_FLAG_PEER_WRITE_CLOSED (1u << 18) /* The peer has closed its write end */ #define IPNET_SOCKET_FLAG_CLOSED (1u << 19) /* The socket has been closed */ #define IPNET_SOCKET_FLAG_DONT_REBIND (1u << 20) /* Never rebind the socket regardless of source address */ #define IPNET_SOCKET_FLAG_MROUTE_CONTROL (1u << 23) /* This socket is used for multicast routing control */ #define IPNET_SOCKET_FLAG_DRAINABLE (1u << 24) /* Packets queued on this socket might be freed in order to satisfy a packet allocation call */ #define IPNET_SOCKET_FLAG_GRE_KEY (1u << 25) /* Socket has a RFC 2890 key set */ /* Socket short term state */ #define IPNET_SOCKET_FLAG_PKTAVAIL_CB_PENDING (1u << 27) /* This socket want an IP_SOEVENT_CB_PKTAVAIL event when the next packet is freed */ /* Misc. */ #define IPNET_SOCKET_FLAG_TIMESTAMPING (1u << 28) #define IPNET_SOCKET_FLAG_DEBUG (1u << 29) /* Debug is enabled */ #define IPNET_SOCKET_FLAG_HAS_STICKY_OPT (1u << 30) /* At least 1 sticky option is set */ #define IPNET_SOCKET_FLAG_SENDMSG_ASYNCHRONOUS (1u << 31) /* socket start index (0,1,2 are reserved) */ #define IPNET_SOCKET_STARTFD 3 /* *=========================================================================== * Ipnet_socket_lookup_key *=========================================================================== */ typedef struct Ipnet_socket_lookup_key_struct { Ip_u32 vr; /* The virtual router the socket must be assigned to */ Ip_u16 domain; /* The domain this socket must be part of */ Ip_u16 proto; /* The protocol the socket must use */ Ip_u16 local_port; /* The local port the socket must bound to */ Ip_u16 peer_port; /* The peer port the socket must connected to */ union Ip_in_addr_union local_addr; /* The local address */ union Ip_in_addr_union peer_addr; /* The peer address */ } Ipnet_socket_lookup_key; /* *=========================================================================== * Ipnet_stats *=========================================================================== * IPNET debug statistics useful for debugging the stack if things go wrong. */ #if defined(IPNET_DEBUG) || defined(IPNET_STATISTICS) typedef struct Ipnet_stats_struct { int pkt_num_tcp_out_of_order_seg; int pkt_num_ip4_reassembly_list; int pkt_num_ip6_reassembly_list; int pkt_input; int pkt_input_err; int pkt_input_opened_err; int pkt_input_bound_to_other_if; int pkt_input_queue_full; int pkt_drain_ip4_reasm; int pkt_drain_ip6_reasm; int pkt_clone_nomem; int pkt_frag_nomem; int pkt_reasm_nomem; int pkt_reasm_too_big; int pkt_queue_enobufs; int pkt_queue_emsgsize; int pkt_output; int pkt_output_drv; int pkt_output_ewouldblock; /* errors other than non-blocking. */ int pkt_output_err; /* errors other than non-blocking. */ int pkt_output_queue; int pkt_output_discard; int pkt_output_delayed; int pkt_output_sleep; int pkt_output_requeue; int pkt_output_fast_drv_ready; int pkt_netif_output_done; int pkt_netif_output_done_pkt; int pkt_netif_output_done_discard; int pkt_netif_output_delayed_queue; int pkt_netif_output_delayed_wake; int pkt_netif_output_user_wake; int pkt_inputd_output; int pkt_inputd_output_err; int pkt_inputd_output_ewouldblock; int pkt_inputd_output_err_nonetif; int eth_input; int eth_input_down; int eth_input_arp; int eth_input_arp_unknown; int eth_input_arp_bad; int eth_input_arp_reperr; int eth_input_arp_reqother; int eth_input_ip4; int eth_input_ip6; int eth_input_other; int eth_output_ip4; int eth_output_ip4_err; int eth_output_ip4_drverr; int eth_output_ip4_multierr; int eth_output_ip6; int eth_output_ip6_err; int eth_output_ip6_drverr; int eth_output_arp_req; int eth_output_arp_req_nomem; int eth_output_arp_rep; #if defined(IPNET_USE_VLAN) || defined(IPNET_USE_VLAN_STACKING) int vlan_input_no_match; int vlan_input_down; #ifdef IPNET_USE_VLAN_STACKING int eth_output_vlan; int eth_output_vlan_drverr; #endif /* IPNET_USE_VLAN_STACKING */ #endif /* IPNET_USE_VLAN || IPNET_USE_VLAN_STACKING */ #ifdef IPNET_USE_BOND int bond_input_no_match; int bond_input_down; #endif /* IPNET_USE_BOND */ int ip4_input; int ip4_input_err; int ip4_input_hdr_trunc; int ip4_input_hdr_toolong; int ip4_input_inval_len; int ip4_input_inval_version; int ip4_input_not_to_me; int ip4_input_iph_badchksum; int ip4_input_reasm_enobufs; int ip4_input_time_exceeded; int ip4_input_need_frag; int ip4_output; int ip4_output_blackhole; int ip4_output_hdr_space; int ip4_output_noroute; int ip4_output_enobufs; int ip4_output_link_err; int icmp4_input; int icmp4_input_echo_request; int icmp4_input_dst_unreach; int icmp4_input_dst_unreach_match; int icmp4_input_dst_unreach_nomatch; int icmp4_input_dst_unreach_badcode; int icmp4_input_hdrsize; int icmp4_input_badchksum; int icmp4_input_hdrsize2; int icmp4_send; int icmp4_send_nomem; int ip6_input; int ip6_input_err; int ip6_input_hdr_trunc; int ip6_input_inval_len; int ip6_input_inval_exthdr; int ip6_input_not_to_me; int ip6_input_too_big; int ip6_input_time_exceeded; int ip6_input_too_short; int ip6_input_tcp_multicast; int ip6_input_prot_err; int ip6_input_hdr_no_next; int ip6_input_raw; int ip6_output; int ip6_output_err; int ip6_output_blackhole; int ip6_output_hdr_space; int ip6_output_noroute; int ip6_output_nomem; int ip6_output_enobufs; int ip6_output_err_probe; int ip6_output_link_err; int icmp6_input; int icmp6_input_err; int icmp6_input_badchksum; int icmp6_input_nomem; int icmp6_send_nomem; int udp4_input; int udp4_input_ok; int udp4_input_err; int tcp4_input; int tcp4_input_ok; int tcp4_input_err; int raw4_input; int raw6_input; int raw_input_badchksum; int udp_input; int udp_input_hdr_trunc; int udp_input_badchksum; int udp_input_sock_multicast; int udp_input_sock_match; int udp_input_sock_nomatch; int udp_input_queue_pkt_ok; int udp_input_queue_pkt_err; int udp_input_multicast; int udp_input_econnrefused; int udp_output; int udp_output_hdr_trunc; int udp_output_eaddrinuse; int udp_output_eafnosupport; int sock_ebadf; int sock_sendmsg; int sock_recvmsg; int sock_recvmsg_tcp_err; int sock_recvmsg_err; int usr_sock_recvmsg; int usr_sock_recvmsg_ewouldblock; int usr_iov_emsgsize; int usr_iov_nomem; int neigh_pending; int neigh_pending_drop; } Ipnet_stats; #define IPNET_STATS(xvar) ipnet->stats.xvar #define IPNET_STAT_LINE(xline) xline #else #define IPNET_STATS(xvar) IP_NOOP #define IPNET_STAT_LINE(xline) IP_NOOP #endif #ifdef IPNET_USE_DIFFSERV typedef struct Ipnet_diffserv_data_struct { /* Array of diffserv handlers */ Ipnet_diffserv_handlers *handlers[IPNET_DIFFSERV_MAX_HANDLERS]; /* Database of meter/marker constructors */ Ipcom_hash *meter_marker_ctor_db; #ifdef IPNET_DIFFSERV_CLASSIFIER_MODE_BA /* Defines which marker/meter to use for each traffic class */ Ip_u32 mapping_active[8]; Ip_u8 ds_to_handler_map[256]; #else /* The classifier used by diffserv */ Ipnet_classifier *classifier; #endif } Ipnet_diffserv_data; #endif /* IPNET_USE_DIFFSERV */ /* *=========================================================================== * Ipnet_inq *=========================================================================== * */ typedef struct Ipnet_input_queue_struct { /* Stack input queue. */ Ipcom_spinlock lock; /* Protects head, tail and count variables */ Ipcom_pkt *head; /* Head of the input queue (first packet to be processed) */ Ipcom_pkt *tail; /* Tail of the input queue (last packet to be processed) */ int count; /* Number of packets currently in the input queue */ #ifdef IPCOM_USE_JOB_QUEUE Ipcom_singleton_job_t job; /* Job for processing this input queue */ #endif } Ipnet_inq; /* *=========================================================================== * Ipnet_task *=========================================================================== * Information that is per IPNET daemon task. */ typedef struct Ipnet_task_struct { Ipcom_pipe *pipe; /* Pipe the net-task polls for stack requests */ Ipcom_pipe *rpipe; /* Pipe the net-task uses to send responses. Used if the sig->response_pipe is IP_NULL */ Ip_pid_t pid; /* PID of the ipnet daemon if IPCOM_USE_JOB_QUEUE is undefined. PID of the job daemon if IPCOM_USE_JOB_QUEUE is defined */ Ipnet_inq inq; /* Packet inqueue served by this daemon */ #ifndef IPCOM_USE_JOB_QUEUE volatile Ip_bool wakeup_pending; /* IP_TRUE if at least one wakeup signal is pending */ Ipnet_sig *wakeup_sig; Ip_u8 wakeup_sig_buf[sizeof(Ipnet_sig) - sizeof(union Ipnet_sig_data_u)]; #endif } Ipnet_task; /* *=========================================================================== * Ipnet_slabs *=========================================================================== * All the slab caches used by IPNET */ typedef struct Ipnet_slabs_struct { #ifdef IPNET_USE_PACKET_POOL Ipcom_memory_cache *pkt_hdr; Ipcom_memory_cache *pkt_buf_1500; Ipcom_memory_cache *pkt_buf_3000; Ipcom_memory_cache *pkt_buf_10000; Ipcom_memory_cache *pkt_buf_65535; #endif #ifndef IPCOM_FORWARDER_NAE Ipcom_memory_cache *socket; Ipcom_memory_cache *bound_port; #else Ipcom_memory_cache *local_socket; #endif Ipcom_memory_cache *timer; Ipcom_memory_cache *kioevent_softirq; Ipcom_memory_cache *poll; } Ipnet_slabs; /* #define IPNET_USE_EVENTLOG */ #ifdef IPNET_USE_EVENTLOG struct Ipnet_events { Ipcom_eventlog log; Ipcom_event sock; Ipcom_event netif; Ipcom_event drv; Ipcom_event drv_wouldblock; }; #endif #ifdef IPNET_USE_PACKET_POOL /* *=========================================================================== * Ipnet_pkt_cache *=========================================================================== */ /* * Maximum number of packets that are allowd to be in the packet pool * cache. This number is a suggestion, the actual number used is * stored in "ipnet->pkt_cache.cnt_mask". */ #define IPNET_PKT_CACHE_MAX_COUNT (1 << 5) typedef struct Ipnet_pkt_cache_entry_struct { /* * Protects the 'top' and 'stack' members. */ Ipcom_spinlock lock; /* * Index to the current top of stack. The stack is empty if 'top' * == IPNET_PKT_CACHE_MAX_COUNT and fullt if 'top' == 0. */ unsigned top; Ipcom_pkt *stack[IPNET_PKT_CACHE_MAX_COUNT]; } Ipnet_pkt_cache_entry; typedef struct Ipnet_pkt_cache_struct { /* * Packets can be alloced by any task, it is therefore not * possible to schedule a new timeout directly in * ipcom_pkt_malloc() or ipcom_pkt_free() as that must be done * from the IPNET task. */ Ipnet_softirq softirq; /* * GC timer for the packet pool cache. All cached packets will be * freed back to the slab allocator if the packet cache has not * been used since the last time this timer expired. */ Ipnet_timeout *tmo; /* * Packet header cache */ Ipnet_pkt_cache_entry hdrs; /* * Cache of packet header + packet buffer with an MTU of 1500. */ Ipnet_pkt_cache_entry pkts; } Ipnet_pkt_cache; #endif /* IPNET_USE_PACKET_POOL */ /* *=========================================================================== * Ipnet_conf *=========================================================================== * See /config/ipnet_config.c for a description of each variable. */ struct Ipnet_sock_conf { int anon_port_min; int anon_port_max; int default_send_buf_size; int default_recv_buf_size; int addr_notify; }; struct Ipnet_route_conf { unsigned max_clone_count; unsigned neigh_rate_period; unsigned neigh_rate_limit; }; #ifdef IPCOM_USE_INET struct Ipnet_inet_conf { Ip_bool sock_stream_dont_frag; Ip_bool udp_checksum; int icmp_rate_limit_bucket_size; int icmp_rate_limit_interval; #ifdef IPNET_USE_RFC3927 char *ll_if_list; #endif Ip_bool multicast_per_interface_filter; Ip_bool random_ip_id; }; #endif /* IPCOM_USE_INET */ #ifdef IPCOM_USE_INET6 struct Ipnet_inet6_conf { int icmp_rate_limit_bucket_size; int icmp_rate_limit_interval; }; #endif /* IPCOM_USE_INET6 */ struct Ipnet_conf { struct Ipnet_sock_conf sock; struct Ipnet_route_conf route; #ifdef IPCOM_USE_INET struct Ipnet_inet_conf inet; #endif #ifdef IPCOM_USE_INET6 struct Ipnet_inet6_conf inet6; #endif }; /* *=========================================================================== * Ipnet_data *=========================================================================== */ #ifdef IPNET_USE_NETLINK struct Ipnet_rtnetlink_table; #endif typedef struct Ipnet_data_struct { /* Dynamic configuration */ struct Ipnet_conf conf; Ipcom_memory_pool *memory_pool; Ipnet_slabs slabs; /* Timeout */ Ip_u32 sec_now; /* The current time with seconds as resolution */ Ip_s64 msec_now; /* The current time with milliseconds as resolution */ Ip_s64 msec_last; /* Used to update the sec_now correctly */ Ip_s64 msec_boot; /* Used to update the sec_now correctly */ Ipcom_pqueue *timeouts; /* Priority queue of timeouts */ Ip_bool update_internal_timer; /* IP_TRUE if the internal timer should be updated when scheduleing the next timeout */ /* * Static timeout to neighbor rate limit. */ Ipnet_timeout *neigh_rate_tmo; /* * The number of new created neighbors in one rate limit period. */ Ip_u32 neigh_current_number; #ifdef IPCOM_USE_JOB_QUEUE Ip_bool force_update_time; /* IP_TRUE if the internal time should be updated when scheduleing the next timeout */ Ipcom_singleton_job_t timeout_job; /* Handle for timeout processing job */ #endif #ifdef IPNET_DEBUG Ip_size_t tmo_map_size; Ipnet_cmd_tmo_handler_to_str *tmo_map; #endif /* Soft interrupts, softirq_xxx can only be modified with interrupts disabled */ Ipcom_spinlock softirq_lock; /* Protects all 'softirq_xxx' variables */ Ip_bool softirq_pending; /* Set to IP_TRUE if at least 1 soft interrupt is pending */ Ipnet_softirq *softirq_head; /* Points to the first soft interrupt to run */ Ipnet_softirq *softirq_tail; /* Points to the last soft interrupt to run */ #ifdef IPCOM_USE_JOB_QUEUE Ipcom_singleton_job_t softirq_job; /* Handle for softirq processing job */ #endif Ipnet_softirq drain_softirq; /* Static buffer to signal drain soft interrupts */ Ipnet_softirq pktavail_softirq; /* Static buffer to signal packet available soft interrupts */ Ipnet_softirq pktnew_softirq; /* Static buffer to that more packets must be added to the pool */ #ifdef IPNET_USE_PACKET_POOL /* Packet pool */ Ipcom_spinlock pkt_pool_lock; /* Protects the slab caches used to implement the pool */ unsigned pkt_pool_wait_cnt; /* Number of processes waiting (on pkt_pool_sem) or about to wait for more free packets in this pool */ Ipcom_sem pkt_pool_sem; /* Semaphore used to put processes to sleep while they wait for more packets to become available in this pool. */ Ipnet_timeout *pkt_pool_tmo; /* Protected by the timeout lock: next wakeup for processes waiting for more packets to become available */ Ipnet_pkt_cache pkt_cache; #ifdef IPNET_DEBUG Ipcom_pkt *allocated_pkt_list; /* List of currently allocated packets */ #endif #endif /* IPNET_USE_PACKET_POOL */ /* * Size of the largest possible socket structure that this system * may use. */ Ip_size_t largest_socket_size; /* * The socket structure must be freed by the network task. Sockets * will not be freed while processing the IPNET_SIG_CLOSE signal * if there is one more more packets sent in the context of the * socket that still hasn't been freed. The packet destructor will * in this case free the socket if the free call is processed by * the stack task. If the free call is processed in another * context, an IPNET_SIG_SOCKFREE_ASYNC will be sent and the * socket will be set in 'async_socket_close_set'. Note that * these member may only be accessed while holding the * 'sockets_lock'. */ Ip_bool async_socket_close_pending; Ip_fd_set async_socket_close_set; Ip_u8 async_socket_close_sig[sizeof(Ipnet_sig) - sizeof(union Ipnet_sig_data_u)]; /* * Mapping from socket descriptor used in the BSD socket API to * the corresponding Ipnet_socket instance. 'sockets' is an array * of length 'ipnet_conf_max_sockets'. * Note for NAE builds: the memory pointed to by 'sockets' is * located in memory shared by all NAE instances. */ Ipcom_spinlock sockets_lock; /* Lock that protects the 'sockets' member */ Ipnet_socket **sockets; /* Array of socket pointers, ipnet_conf_max_sockets entries */ /* * 'reachable_sockets' is an array of list heads of length * 'reachable_socket_len'. Each list contains zero or more * Ipnet_socket instances chained with the 'reachable_list' * member. A socket lookup is done by calculating a hash value * based of source address/port, destination address/port, IP * protocol and VR index. That hash value is used as an index into * the reachable_sockets array. Each socket in the list is tested * until a match is found or all sockets has been investigated (no * matching socket). * Note for NAE builds: the memory pointed to by * 'reachable_sockets' is located in memory shared by all NAE * instances. */ Ipcom_list *reachable_sockets; Ip_size_t reachable_sockets_len; /* * 'bound_ports' is a list that contains zero or more * Ipnet_bound_socket instances chained with the 'list' * member. This structure keep track of which ports that are in * use for a specific IP-protocol, socket domain and VR-index. * Note for NAE builds: the memory pointed to by * 'bound_ports' is located in memory shared by all NAE * instances. */ Ipcom_list *bound_ports; /* * The PID of the process that sent the signal that we are * currently processing. This is needed since the BSD socket API * calls is handled by the network stack task on behalf of the * task/process using the BSD socket API. */ Ip_pid_t effective_pid; #if IPCOM_VR_MAX > 1 Ip_u16 effective_vr; #endif Ip_fd last_fd; /* Last returned fd */ Ip_u32 last_policy; /* Last assigned policy identifier */ #ifdef IPCOM_USE_PACKET int num_packet_sock; /* Number of packet sockets currently active */ #endif /* Router variables */ int route_cache_id; /* The current route cache ID, used to determine if a cached router entry can still be valid */ Ipcom_hash *rtabs; /* Table where all route table head are stored */ Ipcom_hash *policy_routing_rules; /* Table with all policy routing lists (one for each domain/virtual router tuple) */ unsigned cloned_route_count; /* Total number of cloned routes */ Ipcom_hash *queue_db; /* Collection of queue constructors */ Ipnet_inq inq; /* Queue for RX packets + task that inputs them to the stack */ Ipnet_task task; /* Link/interface layer. */ Ipcom_hash *netifs; /* Hash table that contains all attached interfaces */ #ifdef IPNET_USE_6OVER4 Ipnet_netif **netif_6over4; /* Array of active 6over4 interfaces */ int netif_6over4_count; #endif Ipcom_if_eventcb if_eventcb[IPNET_MAX_IF_EVENTCB]; #ifdef IPNET_USE_FAST_IFNAME_LOOKUP Ipcom_hash *ifname_tab; /* Interface name hash table */ #endif /* IPNET_USE_FAST_IFNAME_LOOKUP */ #ifdef IPNET_USE_ROUTE_TABLE_NAMES Ipcom_hash *rtab_names; #endif /* IPNET_USE_ROUTE_TABLE_NAMES */ #ifdef IPNET_USE_ROUTE_COOKIES Ipcom_hash *rtab_cookies; #endif /* IPNET_USE_ROUTE_COOKIES */ Ip_u32 next_ifindex; /* The next ifindex to use */ Ipnet_if_attach_handler if_attach_handler; /* OS port specific to attach new devices to the stack */ /* * Temporary storage to create log messages, anything stored here * might be overwritten by any function. */ char log_buf[256]; /* Statistics */ #if defined(IPNET_DEBUG) || defined(IPNET_STATISTICS) Ipnet_stats stats; #endif #if defined(IP_X_SIOCSDEBUG) || defined(IP_X_SIOCGDEBUG) /* * Value that can be manipulated via the * IP_X_SIOCSDEBUG/IP_X_SIOCGDEBUG ioctl(). This value is not used * anywhere in the stack. The indented usage is to create * breakpoints that will only trigger if 'debug' has a specific * value. */ int debug; #endif /* IP version 4 */ #ifdef IPCOM_USE_INET Ipnet_ip4_data ip4; /* Multicast routing */ #ifdef IPNET_USE_MCAST_ROUTING Ipcom_hash *ip4_mcast; #endif #endif /* IPCOM_USE_INET */ /* IP version 6 */ #ifdef IPCOM_USE_INET6 Ipnet_ip6_data ip6; #ifdef IPNET_USE_MCAST_ROUTING Ipcom_hash *ip6_mcast; #endif #endif /* PPP and PPPoE support */ #ifdef IPPPP Ipppp_ipstack_data ppp; #endif /* Differentiated Services */ #ifdef IPNET_USE_DIFFSERV Ipnet_diffserv_data diffserv; #endif /* IPNET_USE_DIFFSERV */ /* NAT */ #ifdef IPNET_USE_NAT Ipnet_nat_data nat; #endif /* Route/netlink sockets. */ #ifdef IPNET_USE_ROUTESOCK int num_route_sock; /* Number of routing sockets. */ #endif #ifdef IPNET_USE_NETLINKSOCK int num_netlink_sock; /* Number of netlink sockets. */ struct Ip_rtnl_link_ops *rtnetlink_ops; #endif #ifdef IPNET_USE_NETLINK void *netlink_data[IP_NETLINK_MAX]; #endif /* MIB-2 */ #ifdef IPCOM_USE_MIB2 Ipcom_mib2_stats mib2; #endif /* VLAN stacking */ #ifdef IPNET_USE_VLAN_STACKING Ip_u16 vlan_s_tpid; Ip_u16 vlan_s_tpid_net; /* S-VLAN TPID in network order format */ #endif #ifdef IPBRIDGE struct Ipnet_bridge_st *bridge; /* Bridge control structure */ #endif } Ipnet_data; /* Ipnet_data flags: */ #define IPNET_FLAG_IPV4_FORWARD_PKT 0x02 /* Set if IPv4 packets should be forward */ #define IPNET_FLAG_IPV6_FORWARD_PKT 0x04 /* Set if IPv6 packets should be forward */ #define IPNET_FLAG_PKTAVAIL_CB_PENDING 0x10 /* A non-blocking socket call, on a socket with a */ /* callback handler, failed due to no packets in the packet pool */ #define IPNET_FLAG_IPV6_RFC4941_INIT 0x20 /* IPv6 privacy extension has been initialized */ /* * Set to put IPNET in strict mode, unset for loose mode. * Strict mode requires packet to enter on the correct interface to be * considered local. Loose mode will accept the packet if any interface * has the unicast address. Most OS:es uses loose mode. */ #define IPNET_FLAG_IPV4_STRICT_MODE 0x40 /* Set to enable ipv4 strict mode in ipnet stack */ #define IPNET_FLAG_IPV6_STRICT_MODE 0x80 /* Set to enable ipv6 strict mode in ipnet stack */ #ifdef IPCOM_FORWARDER_NAE /* * IPNET shared memory control block */ typedef struct Ipnet_shm_struct { /* * Shared memory is initialized to all zeros, so this variable * starts out as IP_FALSE. */ Ip_bool is_initialized; /* * Array of socket pointers. The length of the array is * ipnet_conf_max_sockets. */ Ipnet_socket **sockets; /* * reachable_sockets is an array of list of sockets. A socket that * is ready to accept ingress traffic is put into the list * with index (socket_hash_val % reachable_sockets_len). */ Ipcom_list *reachable_sockets; Ip_size_t reachable_sockets_len; /* * 'bound_ports' is the list of ports in use. Each port is * represented by a Ipnet_bound_port structure. */ Ipcom_list *bound_ports; /* * Array of lists of Ipnet_peer_info entries. */ Ipcom_list *peer_info_buckets; Ip_size_t peer_info_buckets_len; } Ipnet_shm; #endif /* IPCOM_FORWARDER_NAE */ /* *=========================================================================== * Ipnet_lock_state *=========================================================================== */ #ifdef IP_PORT_LKM typedef struct Ipnet_lock_state_struct { Ip_bool has_write_lock; Ip_bool has_snd_rcv_lock; Ipnet_socket *sock; } Ipnet_lock_state; #endif /* **************************************************************************** * 6 PROTOTYPES **************************************************************************** */ IP_EXTERN IP_FASTDATA Ipnet_data *ipnet; IP_EXTERN IP_FASTDATA Ipnet_sock_ops **ipnet_sock_ops; IP_EXTERN Ip_u32 ipnet_flags; IP_EXTERN Ipcom_cmd_int_str_map ipnet_bool_map[]; /* *=========================================================================== * Driver/link upcalls *=========================================================================== */ /* Note: The caller must be IPNET code locked to call ipnet_kioevent() */ IP_PUBLIC void ipnet_kioevent(Ipnet_netif *netif, int command, void *data, int fcflags); /* *=========================================================================== * IPNET Internal *=========================================================================== */ /* *=========================================================================== * ipnet_ipaddrlen *=========================================================================== * Description: Returns the length of the IP address. * Parameters: domain - domain for the neighbor. * Returns: * */ IP_INLINE Ip_size_t ipnet_ipaddrlen(int domain) { IPCOM_UNUSED_ARG(domain); #ifdef IPCOM_USE_INET6 if (domain == IP_AF_INET6) return sizeof(struct Ip_in6_addr); #endif return sizeof(struct Ip_in_addr); } IP_GLOBAL void ipcom_pause_os_network_daemon(void); IP_GLOBAL void ipnet_pause_os_network_daemon(void); IP_GLOBAL void ipnet_resume_os_network_daemon(void); #if IPCOM_VR_MAX > 1 #define ipnet_get_effective_vr() ipnet->effective_vr #else #define ipnet_get_effective_vr() 0 #endif #define ipnet_get_effective_pid() ipnet->effective_pid IP_GLOBAL void ipnet_try_free_mem(Ip_bool run_async); IP_GLOBAL int ipnet_sysvar_get_as_int_vr(Ipnet_netif *netif, IP_CONST char *snd, IP_CONST char *name, int default_val, IP_CONST Ipcom_cmd_int_str_map *map, int vr); IP_GLOBAL int ipnet_sysvar_netif_get_as_int(int domain, Ipnet_netif *netif, IP_CONST char *name, int default_val); IP_GLOBAL int ipnet_sysvar_netif_get_as_int_ex(int domain, Ipnet_netif *netif, IP_CONST char *name, int default_val, IP_CONST Ipcom_cmd_int_str_map *map); IP_GLOBAL Ip_u32 ipnet_sec_now(void); IP_GLOBAL Ip_s64 ipnet_msec_now(void); IP_GLOBAL Ip_bool ipnet_is_stack_task(void); IP_GLOBAL Ipcom_pkt *ipnet_pkt_clone(Ipcom_pkt *pkt, int is_ipstart_valid); IP_GLOBAL void * ipnet_sysctl_if_add_addrs_one(void *buf, Ipnet_netif *netif, int domain, void *addrx, Ip_size_t *lenp); IP_GLOBAL Ip_bool ipnet_has_priv(int priv); IP_PUBLIC Ip_s64 ipnet_timeval_to_msec(struct Ip_timeval *tv); #ifdef IPCOM_USE_MIB2 IP_GLOBAL Ipnet_netif *ipnet_ip6_socket_to_netif(struct Ipnet_socket_struct *sock); #endif #ifdef IPCOM_USE_MIB2_NEW IP_GLOBAL void ipnet_eth_update_mib2_lastchange(Ipnet_neigh *n); #endif IP_GLOBAL Ip_u16 ipnet_sysctl_create_ifinfo(void *buf, Ipnet_netif *netif); IP_GLOBAL Ip_u32 ipnet_stats_tcp_established(void); IP_GLOBAL void ipnet_loop_pkt_tx(Ipnet_dst_cache *dst, Ipcom_pkt *pkt, Ipnet_dst_cache_domain_ctor dst_cache_local_tx_ctor); IP_GLOBAL Ipnet_dst_cache * ipnet_ip4_dst_cache_get(Ip_u16 vr, const struct Ip_in_addr *to, const struct Ip_in_addr *from, Ip_u8 tos, unsigned egress_ifindex, unsigned ingress_ifindex); IP_GLOBAL int ipnet_fw_nat_ipsec_tx(Ipnet_dst_cache **dstp, Ipcom_pkt **pktp, Ip_bool do_nat); IP_GLOBAL int ipnet_fw_nat_rx(Ipnet_dst_cache **dstp, Ipcom_pkt **pktp, Ip_bool do_nat, Ip_bool fw_checked); IP_GLOBAL void ipnet_conf_update(const char *fst, const char *snd, const char *name); IP_GLOBAL int ipnet_ctrl_sig(Ipnet_sig *sig); /* *=========================================================================== * IPNET socket *=========================================================================== */ /* *=========================================================================== * ipnet_sock_make_next_sendmsg_synchronous *=========================================================================== * Description: Makes sure that the next call to sendmsg() is * synchronous so that proper error code is returned. * Parameters: sock - a socket * Returns: * */ IP_INLINE void ipnet_sock_make_next_sendmsg_synchronous(Ipnet_socket *sock) { /* * This variable is compared to ipnet->route_cache_id and the * sendmsg() call can be asynchronous if they are * equal. ipnet->route_cache_id will never have a value of zero. */ sock->snd_route_cache_id = 0; } IP_GLOBAL void ipnet_sock_update_reuse(Ipnet_socket *sock); IP_GLOBAL Ip_size_t ipnet_sock_get_bound_port_size(void); IP_GLOBAL Ipnet_socket *ipnet_sock_get(Ipnet_socket_lookup_key *key, Ipcom_list **head); IP_GLOBAL Ipnet_socket *ipnet_sock_next(Ipnet_socket *sock); IP_GLOBAL Ip_bool ipnet_sock_has_waiting_writers(Ipnet_socket *sock); IP_GLOBAL Ip_bool ipnet_is_sock_readable(Ipnet_socket *sock, int lowat); IP_GLOBAL Ip_bool ipnet_is_sock_writable(Ipnet_socket *sock, int lowat); IP_GLOBAL Ip_bool ipnet_is_sock_exceptional(Ipnet_socket *sock, int lowat); IP_PUBLIC void ipnet_sock_data_avail(Ipnet_socket *sock, int so_errno, int how); IP_GLOBAL void ipnet_sock_pkt_drain(void); IP_GLOBAL void *ipnet_sock_alloc_private_data(Ipnet_socket *sock, Ip_size_t size); #ifdef IPNET_USE_ROUTER_ALERT IP_GLOBAL int ipnet_sock_join_router_alert_chain(Ipnet_socket *sock); IP_GLOBAL int ipnet_sock_leave_router_alert_chain(Ipnet_socket *sock); #endif IP_GLOBAL int ipnet_sock_router_alert_pkt(Ipcom_pkt *pkt); IP_GLOBAL int ipnet_configd_start(void); IP_GLOBAL int ipnet_raw_input(Ipcom_pkt *pkt, Ip_bool take_ownership, int proto, IP_CONST void *src_addr, Ip_u16 src_port, IP_CONST void *dst_addr, Ip_u16 dst_port, Ipnet_sock_lookup_f socklookup); IP_GLOBAL int ipnet_sock_bind(Ipnet_socket *sock, IP_CONST struct Ip_sockaddr *name, Ip_socklen_t namelen, Ip_bool check_resuse); IP_GLOBAL Ip_u16 ipnet_next_ephemeral_port(Ipnet_socket *sock); IP_GLOBAL int ipnet_queue_received_packet(Ipcom_pkt *pkt, Ipnet_socket *sock); IP_GLOBAL void ipnet_sock_free(Ipnet_socket *sock, Ip_bool clear_sockets_arr); IP_GLOBAL int ipnet_do_close(Ipnet_socket *sock); IP_GLOBAL int ipnet_do_socketselect(int nfds, Ip_fd_set *readfds, Ip_fd_set *writefds, Ip_fd_set *exceptfds, struct Ip_timeval *timeout); IP_GLOBAL int ipnet_sock_drop_all_multicast_memberships(Ipnet_socket *sock, Ipnet_netif *netif, Ip_bool drop_ip4, Ip_bool drop_ip6); IP_GLOBAL int ipnet_increase_hdr_space(Ipcom_pkt **ppkt, Ip_bool is_iphdr_valid); IP_GLOBAL Ipnet_route_entry * ipnet_sock_get_route(Ipnet_socket *sock); IP_GLOBAL int ipnet_ioctl_move_if_rt_to_vr(Ipnet_netif *netif, Ip_u16 vr); IP_GLOBAL int ipnet_sock_create_lookup_tables(void); IP_GLOBAL int ipnet_sock_set_reachable(Ipnet_socket *sock); IP_GLOBAL void ipnet_sock_set_unreachable(Ipnet_socket *sock); IP_GLOBAL void ipnet_sock_bind_addr_removed(Ipnet_socket *sock_list); IP_GLOBAL void ipnet_sock_change_addr_entry(Ipnet_socket *old_sock_list, Ipnet_socket **pnew_sock_list, void *addr_entry); IP_GLOBAL int ipnet_sock_unconnect(Ipnet_socket *sock); IP_GLOBAL int ipnet_sock_bind_to_port(Ipnet_socket *sock, IP_CONST struct Ip_sockaddr *name, Ip_bool check_reuse); IP_GLOBAL void ipnet_sock_unbind(Ipnet_socket *sock); IP_GLOBAL int ipnet_pkt_get_maxlen(Ipcom_pkt *pkt); IP_INLINE Ipnet_sock_ops *ipnet_sock_get_ops(Ipnet_socket *sock) { /* * For NAE:s * The ipnet_sock_ops array is located in local memory, so the * returned pointer must not be stored in any shared memory area * (like the socket structure for example). This function must be * called each time the socket options in needed. */ ip_assert(sock->ops_handle >= 0); return ipnet_sock_ops[sock->ops_handle]; } IP_GLOBAL int ipnet_sock_get_ops_handle(int domain, int type, int protocol, Ip_bool *no_domain, Ip_bool *no_type); IP_GLOBAL int ipnet_sock_register_ops(Ipnet_sock_ops *ops); #ifdef IPSCTP IP_GLOBAL int ipnet_sock_sctp_register(void); #endif IP_GLOBAL int ipnet_sock_udp_register(void); #ifdef IPTCP IP_GLOBAL int ipnet_sock_tcp_register(void); #endif #ifdef IPCOM_USE_INET IP_GLOBAL int ipnet_sock_ip4_register(void); IP_GLOBAL void ipnet_ip4_reg_transport_layer(Ip_u8 ip_proto, Ipnet_transport_layer_rx_func trans_rx); #endif #ifdef IPCOM_USE_INET6 IP_GLOBAL int ipnet_sock_ip6_register(void); IP_GLOBAL void ipnet_ip6_reg_transport_layer(Ip_u8 ip_proto, Ipnet_transport_layer_rx_func trans_rx); #endif #ifdef IPNET_USE_ROUTESOCK IP_GLOBAL int ipnet_sock_route_register(void); #endif #ifdef IPNET_USE_NETLINKSOCK IP_GLOBAL int ipnet_sock_netlink_register(void); #endif #ifdef IPCOM_USE_PACKET IP_GLOBAL int ipnet_sock_packet_register(void); #endif #ifdef IPIPSEC2 IP_GLOBAL void ipnet_ipsec_rx(Ipnet_dst_cache *dst, Ipcom_pkt *pkt, Ip_u8 proto); IP_GLOBAL int ipnet_proto_ah_register(void); IP_GLOBAL int ipnet_proto_esp_register(void); IP_GLOBAL int ipnet_sock_key_register(void); #endif #ifdef IPNET_USE_SOCKDEV IP_GLOBAL int ipnet_sock_sockdev_register(void); #endif IP_GLOBAL void ipnet_sock_ip4_get_ops(Ipnet_sock_inet_ops *ops); IP_GLOBAL void ipnet_sock_ip6_get_ops(Ipnet_sock_inet_ops *ops); #ifdef IPCOM_FORWARDER_NAE IP_GLOBAL void ipnet_nae_unsupported_transport_layer_rx(Ipnet_dst_cache *dst, Ipcom_pkt *pkt); #endif /* *=========================================================================== * socket function callable by IPNET in user context *=========================================================================== */ IP_GLOBAL int ipnet_usr_sock_pkt_recv(Ipnet_socket *sock, struct Ip_msghdr *msg, int flags); /* *=========================================================================== * IPNET packet socket *=========================================================================== */ #ifdef IPCOM_USE_PACKET IP_GLOBAL Ip_bool ipnet_packet_input(Ipnet_netif *netif, Ipcom_pkt *pkt); IP_GLOBAL int ipnet_packet_output(Ipnet_socket *sock, IP_CONST struct Ip_msghdr *msg, Ipcom_pkt *pkt); IP_GLOBAL Ip_bool ipnet_packet_getsockopt(int optname, IP_CONST struct Ip_packet_mreq *mreq, Ip_socklen_t *optlen); IP_GLOBAL Ip_bool ipnet_packet_setsockopt(Ipnet_socket *sock, int optname, IP_CONST struct Ip_packet_mreq *mreq, Ip_socklen_t optlen); #endif /* IPCOM_USE_PACKET */ /* *=========================================================================== * Fragmentation & reassembly *=========================================================================== */ typedef Ip_bool (*Ipnet_is_part_of_same_pkt_func)(Ipcom_pkt *frag1, Ipcom_pkt *frag2); typedef Ip_bool (*Ipnet_more_fragments_func)(Ipcom_pkt *frag); typedef void (*Ipnet_update_ip_header_func)(Ipcom_pkt *pkt); typedef void (*Ipnet_reassemble_err_func)(Ipcom_pkt *frag_list); IP_GLOBAL Ipcom_pkt * ipnet_reassembly(struct Ipnet_peer_info_struct *peer_info, Ipcom_pkt *pkt, Ipnet_is_part_of_same_pkt_func is_part_of_same_pkt, Ipnet_more_fragments_func more_fragments); IP_GLOBAL Ipcom_pkt * ipnet_create_reassembled_packet(Ipcom_pkt *fragment_list, Ipnet_update_ip_header_func update_ip_header, Ipnet_reassemble_err_func report_reassemble_err); IP_GLOBAL Ipcom_pkt * ipnet_fragment_packet(Ipcom_pkt *pkt, int ip_hdr_size, int other_hdr_size, int mtu, Ipnet_more_fragments_func more_fragments); IP_GLOBAL void ipnet_frag_set_peer_info(Ipcom_pkt *frag, Ipnet_peer_info *peer_info); IP_GLOBAL Ipnet_peer_info * ipnet_frag_to_peer_info(Ipcom_pkt *frag); IP_GLOBAL void ipnet_frag_release_peer_info(Ipcom_pkt *frag); /* *=========================================================================== * ROUTING SOCKET *=========================================================================== * */ #ifdef IPNET_USE_ROUTESOCK IP_GLOBAL void ipnet_routesock_addr_add(struct Ipnet_netif_struct *netif, int domain, void *addr); IP_GLOBAL void ipnet_routesock_addr_delete(struct Ipnet_netif_struct *netif, int domain, void *addr); IP_GLOBAL void ipnet_routesock_addr_conflict(Ipnet_netif *netif, int domain, void *addr); IP_GLOBAL void ipnet_routesock_if_change(struct Ipnet_netif_struct *netif); IP_GLOBAL void ipnet_routesock_if_announce(Ipnet_netif *netif, Ip_u16 what); IP_GLOBAL void ipnet_routesock_rt_add(Ipnet_route_entry *rt); IP_GLOBAL void ipnet_routesock_rt_delete(Ipnet_route_entry *rt); IP_GLOBAL void ipnet_routesock_rt_change(Ipnet_route_entry *rt); IP_GLOBAL void ipnet_routesock_rt_miss(Ipcom_route *rtab, IP_CONST void *key); IP_GLOBAL void ipnet_routesock_rt_redirect(Ipcom_route *rtab, Ip_u32 ifindex, IP_CONST void *dst, IP_CONST void *new_gw); IP_GLOBAL void ipnet_routesock_neigh_resolve(Ipnet_neigh *neigh); #endif /* IPNET_USE_ROUTESOCK */ /* *=========================================================================== * PACKET POOL FUNCTIONS *=========================================================================== * */ #ifdef IPNET_USE_PACKET_POOL IP_GLOBAL int ipnet_pkt_pool_init(void); IP_GLOBAL int ipnet_pkt_pool_hdr_count_hint(void); IP_GLOBAL void ipnet_pkt_pool_drain(); #endif /* IPNET_USE_PACKET_POOL */ /* *=========================================================================== * DEBUG FUNCTIONS *=========================================================================== * */ #ifdef IPNET_DEBUG IP_GLOBAL void ipnet_pkt_remove_from_alloc_list(Ipcom_pkt *pkt); IP_GLOBAL void ipnet_pkt_add_to_alloc_list(Ipcom_pkt *pkt); IP_GLOBAL void ipnet_pkt_check(Ipcom_pkt *pkt); #endif /* IPNET_DEBUG */ /* *=========================================================================== * POWER ON SELF-TEST *=========================================================================== * */ #ifdef IPNET_USE_POST IP_GLOBAL void ipnet_post_run(void); #endif /* *=========================================================================== * ipnet_alloc_snd_bytes *=========================================================================== * Description: Allocate socket send buffer space. * Parameters: sock - a socket. * total_buf_len - number of bytes of space to allocate in the * socket send buffer. * Returns: IP_TRUE if successful; * IP_FALSE if there is currently not enough space; */ IP_INLINE Ip_bool ipnet_alloc_snd_bytes(Ipnet_socket *sock, int total_buf_len) { int snd_bytes; do { snd_bytes = ipcom_atomic_get(&sock->snd_bytes); if (snd_bytes >= sock->send_max_bytes || snd_bytes + total_buf_len < snd_bytes) return 0; } while (!ipcom_atomic_ptr_cas((Ip_ptrdiff_t*)&sock->snd_bytes, snd_bytes, snd_bytes + total_buf_len)); return 1; } #ifdef __cplusplus } #endif #endif /* **************************************************************************** * END OF FILE **************************************************************************** */