[Javanetsim-cvs] IceScan/icesockets queue.h, NONE, 1.1 sock_win.h, 1.6, 1.7 sock_arp.h, 1.5, 1.6 cr
Status: Beta
Brought to you by:
darkkey
From: Alexander B. <da...@us...> - 2006-12-17 15:06:41
|
Update of /cvsroot/javanetsim/IceScan/icesockets In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv2552/icesockets Modified Files: sock_win.h sock_arp.h crawsocket.h csocket.h sock_eth.h Added Files: queue.h Log Message: no message Index: sock_arp.h =================================================================== RCS file: /cvsroot/javanetsim/IceScan/icesockets/sock_arp.h,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** sock_arp.h 17 Dec 2006 12:14:35 -0000 1.5 --- sock_arp.h 17 Dec 2006 15:06:37 -0000 1.6 *************** *** 10,14 **** #include "sock_types.h" ! #include <Iphlpapi.h> icestring get_arp_from_cache(icestring &ip) --- 10,14 ---- #include "sock_types.h" ! icestring get_arp_from_cache(icestring &ip) Index: sock_eth.h =================================================================== RCS file: /cvsroot/javanetsim/IceScan/icesockets/sock_eth.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** sock_eth.h 17 Dec 2006 14:31:24 -0000 1.1 --- sock_eth.h 17 Dec 2006 15:06:37 -0000 1.2 *************** *** 2,6 **** #define _iceeth_H ! #ifndef __CYGWIN__ #include "sock_types.h" --- 2,6 ---- #define _iceeth_H ! #ifdef __WIN32__ #include "sock_types.h" *************** *** 8,24 **** ip_t *i = ip_open(); ! ip_send(i, buf, len); ! ip_close(i); ! return 0; } ! #else ! int send_ip_packet(const void *buf, size_t len){ return 1; } #endif ! #endif \ No newline at end of file --- 8,265 ---- ip_t *i = ip_open(); ! ip_send(i, buf, len); ! ip_close(i); ! return 0; } ! #elif __CYGWIN__ ! int send_ip_packet(const void *buf, size_t len){ return 1; } + + #else + + #include "queue.h" + #include "dnet.h" + + struct ip_intf { + eth_t *eth; + char name[INTF_NAME_LEN]; + struct addr ha; + struct addr pa; + int mtu; + LIST_ENTRY(ip_intf) next; + }; + + struct ip_handle { + arp_t *arp; + intf_t *intf; + route_t *route; + int fd; + struct sockaddr_in sin; + + LIST_HEAD(, ip_intf) ip_intf_list; + }; + + static int + i_add_ip_intf(const struct intf_entry *entry, void *arg) + { + ip_t *ip = (ip_t *)arg; + struct ip_intf *ipi; + + if (entry->intf_type == INTF_TYPE_ETH && + (entry->intf_flags & INTF_FLAG_UP) != 0 && + entry->intf_mtu >= ETH_LEN_MIN && + entry->intf_addr.addr_type == ADDR_TYPE_IP && + entry->intf_link_addr.addr_type == ADDR_TYPE_ETH) { + + if ((ipi = (ip_intf*) calloc(1, sizeof(*ipi))) == NULL) + return (-1); + + strncpy(ipi->name, entry->intf_name, sizeof(ipi->name)); + memcpy(&ipi->ha, &entry->intf_link_addr, sizeof(ipi->ha)); + memcpy(&ipi->pa, &entry->intf_addr, sizeof(ipi->pa)); + ipi->mtu = entry->intf_mtu; + + LIST_INSERT_HEAD(&ip->ip_intf_list, ipi, next); + } + return (0); + } + + ip_t * + i_ip_open(void) + { + ip_t *ip; + + if ((ip = (ip_t*) calloc(1, sizeof(*ip))) != NULL) { + ip->fd = -1; + + if ((ip->arp = arp_open()) == NULL || + (ip->intf = intf_open()) == NULL || + (ip->route = route_open()) == NULL) + return (ip_close(ip)); + + if ((ip->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return (ip_close(ip)); + + memset(&ip->sin, 0, sizeof(ip->sin)); + ip->sin.sin_family = AF_INET; + ip->sin.sin_port = htons(666); + + LIST_INIT(&ip->ip_intf_list); + + if (intf_loop(ip->intf, i_add_ip_intf, ip) != 0) + return (ip_close(ip)); + } + return (ip); + } + + static struct ip_intf * + i_lookup_ip_intf(ip_t *ip, ip_addr_t dst) + { + struct ip_intf *ipi; + int n; + + ip->sin.sin_addr.s_addr = dst; + n = sizeof(ip->sin); + + if (connect(ip->fd, (struct sockaddr *)&ip->sin, n) < 0) + return (NULL); + + if (getsockname(ip->fd, (struct sockaddr *)&ip->sin, (socklen_t *) &n) < 0) + return (NULL); + + LIST_FOREACH(ipi, &ip->ip_intf_list, next) { + if (ipi->pa.addr_ip == ip->sin.sin_addr.s_addr) { + if (ipi->eth == NULL) { + if ((ipi->eth = eth_open(ipi->name)) == NULL) + return (NULL); + } + if (ipi != LIST_FIRST(&ip->ip_intf_list)) { + LIST_REMOVE(ipi, next); + LIST_INSERT_HEAD(&ip->ip_intf_list, ipi, next); + } + return (ipi); + } + } + return (NULL); + } + + static void + i_request_arp(struct ip_intf *ipi, struct addr *dst) + { + u_char frame[ETH_HDR_LEN + ARP_HDR_LEN + ARP_ETHIP_LEN]; + + eth_pack_hdr(frame, ETH_ADDR_BROADCAST, ipi->ha.addr_eth, + ETH_TYPE_ARP); + arp_pack_hdr_ethip(frame + ETH_HDR_LEN, ARP_OP_REQUEST, + ipi->ha.addr_eth, ipi->pa.addr_ip, ETH_ADDR_BROADCAST, + dst->addr_ip); + + eth_send(ipi->eth, frame, sizeof(frame)); + } + + ssize_t + i_ip_send(ip_t *ip, const void *buf, size_t len) + { + struct ip_hdr *iph; + struct ip_intf *ipi; + struct arp_entry arpent; + struct route_entry rtent; + u_char frame[ETH_LEN_MAX]; + int i, usec; + + iph = (struct ip_hdr *)buf; + + if ((ipi = i_lookup_ip_intf(ip, iph->ip_dst)) == NULL) { + errno = EHOSTUNREACH; + return (-1); + } + arpent.arp_pa.addr_type = ADDR_TYPE_IP; + arpent.arp_pa.addr_bits = IP_ADDR_BITS; + arpent.arp_pa.addr_ip = iph->ip_dst; + memcpy(&rtent.route_dst, &arpent.arp_pa, sizeof(rtent.route_dst)); + + for (i = 0, usec = 10; i < 3; i++, usec *= 100) { + if (arp_get(ip->arp, &arpent) == 0) + break; + + if (route_get(ip->route, &rtent) == 0 && + rtent.route_gw.addr_ip != ipi->pa.addr_ip) { + memcpy(&arpent.arp_pa, &rtent.route_gw, + sizeof(arpent.arp_pa)); + if (arp_get(ip->arp, &arpent) == 0) + break; + } + i_request_arp(ipi, &arpent.arp_pa); + + usleep(usec); + } + if (i == 3) + memset(&arpent.arp_ha.addr_eth, 0xff, ETH_ADDR_LEN); + + eth_pack_hdr(frame, arpent.arp_ha.addr_eth, + ipi->ha.addr_eth, ETH_TYPE_IP); + + if (len > ipi->mtu) { + u_char *p, *start, *end, *ip_data; + int ip_hl, fraglen; + + ip_hl = iph->ip_hl << 2; + fraglen = ipi->mtu - ip_hl; + + iph = (struct ip_hdr *)(frame + ETH_HDR_LEN); + memcpy(iph, buf, ip_hl); + ip_data = (u_char *)iph + ip_hl; + + start = (u_char *)buf + ip_hl; + end = (u_char *)buf + len; + + for (p = start; p < end; ) { + memcpy(ip_data, p, fraglen); + + iph->ip_len = htons(ip_hl + fraglen); + iph->ip_off = htons(((p + fraglen < end) ? IP_MF : 0) | + ((p - start) >> 3)); + + ip_checksum(iph, ip_hl + fraglen); + + i = ETH_HDR_LEN + ip_hl + fraglen; + if (eth_send(ipi->eth, frame, i) != i) + return (-1); + p += fraglen; + if (end - p < fraglen) + fraglen = end - p; + } + return (len); + } + memcpy(frame + ETH_HDR_LEN, buf, len); + i = ETH_HDR_LEN + len; + if (eth_send(ipi->eth, frame, i) != i) + return (-1); + + return (len); + } + + ip_t * + i_ip_close(ip_t *ip) + { + struct ip_intf *ipi, *nxt; + + if (ip != NULL) { + for (ipi = LIST_FIRST(&ip->ip_intf_list); + ipi != LIST_END(&ip->ip_intf_list); ipi = nxt) { + nxt = LIST_NEXT(ipi, next); + if (ipi->eth != NULL) + eth_close(ipi->eth); + free(ipi); + } + if (ip->fd >= 0) + close(ip->fd); + if (ip->route != NULL) + route_close(ip->route); + if (ip->intf != NULL) + intf_close(ip->intf); + if (ip->arp != NULL) + arp_close(ip->arp); + free(ip); + } + return (NULL); + } + + int send_ip_packet(const void *buf, size_t len){ + ip_t *i = i_ip_open(); + + i_ip_send(i, buf, len); + + i_ip_close(i); + + return 0; + } + #endif ! #endif Index: crawsocket.h =================================================================== RCS file: /cvsroot/javanetsim/IceScan/icesockets/crawsocket.h,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** crawsocket.h 17 Dec 2006 14:23:15 -0000 1.16 --- crawsocket.h 17 Dec 2006 15:06:37 -0000 1.17 *************** *** 132,144 **** } ! int send_tcp_raw( icestring source, icestring destination, unsigned short sport, unsigned short dport, unsigned long seq, unsigned long ack, unsigned char flags, unsigned short window, char *data, const unsigned short datalen) { ! #ifdef WIN32 ! char *packet = (char *) malloc(sizeof(struct iphdr) + sizeof(struct tcphdr) + datalen); ! #else ! char packet[sizeof(struct iphdr) + sizeof(struct tcphdr) + datalen]; ! #endif struct iphdr *ip = (struct iphdr *) packet; --- 132,144 ---- } ! int send_tcp_raw(bool ethernet, icestring source, icestring destination, unsigned short sport, unsigned short dport, unsigned long seq, unsigned long ack, unsigned char flags, unsigned short window, char *data, const unsigned short datalen) { ! #ifdef WIN32 ! char *packet = (char *) malloc(sizeof(struct iphdr) + sizeof(struct tcphdr) + datalen); ! #else ! char packet[sizeof(struct iphdr) + sizeof(struct tcphdr) + datalen]; ! #endif struct iphdr *ip = (struct iphdr *) packet; *************** *** 197,212 **** //print_tcppacket(packet,ntohs(ip->tot_len)); ! #ifndef WIN32 ! if ((res = sendto(destination.c_str(), packet, ntohs(ip->tot_len), 0)) == -1) { perror("sendto in send_tcp_raw"); ! free(packet); return -1; } - #else - res = send_ip_packet(packet, ntohs(ip->tot_len)); - #endif ! free(packet); return res; } --- 197,216 ---- //print_tcppacket(packet,ntohs(ip->tot_len)); ! if(ethernet){ ! res = send_ip_packet(packet, ntohs(ip->tot_len)); ! }else if ((res = sendto(destination.c_str(), packet, ntohs(ip->tot_len), 0)) == -1) { perror("sendto in send_tcp_raw"); ! #ifdef WIN32 ! free(packet); ! #endif return -1; } ! ! ! #ifdef WIN32 ! free(packet); ! #endif return res; } Index: csocket.h =================================================================== RCS file: /cvsroot/javanetsim/IceScan/icesockets/csocket.h,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** csocket.h 17 Dec 2006 12:14:35 -0000 1.23 --- csocket.h 17 Dec 2006 15:06:37 -0000 1.24 *************** *** 97,102 **** ~csocket(){ /*std::cout << "CSCOCKET destroyed." << (cs_id) << std::endl; */ } - - int connect(const char *hostname, int port, int timeout = NULL){ struct sockaddr_in saddress; --- 97,100 ---- Index: sock_win.h =================================================================== RCS file: /cvsroot/javanetsim/IceScan/icesockets/sock_win.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** sock_win.h 17 Dec 2006 14:23:15 -0000 1.6 --- sock_win.h 17 Dec 2006 15:06:37 -0000 1.7 *************** *** 27,32 **** #include <winsock2.h> ! #include <ws2tcpip.h> ! #include <process.h> WSADATA start_sockets(){ --- 27,33 ---- #include <winsock2.h> ! #include <ws2tcpip.h> ! #include <process.h> ! #include <Iphlpapi.h> WSADATA start_sockets(){ --- NEW FILE: queue.h --- /* $OpenBSD: queue.h,v 1.22 2001/06/23 04:39:35 angelos Exp $ */ /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ #ifndef _SYS_QUEUE_H_ #define _SYS_QUEUE_H_ /* * This file defines five types of data structures: singly-linked lists, * lists, simple queues, tail queues, and circular queues. * * * A singly-linked list is headed by a single forward pointer. The elements * are singly linked for minimum space and pointer manipulation overhead at * the expense of O(n) removal for arbitrary elements. New elements can be * added to the list after an existing element or at the head of the list. * Elements being removed from the head of the list should use the explicit * macro for this purpose for optimum efficiency. A singly-linked list may * only be traversed in the forward direction. Singly-linked lists are ideal * for applications with large datasets and few or no removals or for * implementing a LIFO queue. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list * may only be traversed in the forward direction. * * A simple queue is headed by a pair of pointers, one the head of the * list and the other to the tail of the list. The elements are singly * linked to save space, so elements can only be removed from the * head of the list. New elements can be added to the list before or after * an existing element, at the head of the list, or at the end of the * list. A simple queue may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * * A circle queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or after * an existing element, at the head of the list, or at the end of the list. * A circle queue may be traversed in either direction, but has a more * complex end of list detection. * * For details on the use of these macros, see the queue(3) manual page. */ /* * Singly-linked List definitions. */ #define SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } #define SLIST_HEAD_INITIALIZER(head) \ { NULL } #define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } /* * Singly-linked List access methods. */ #define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_END(head) NULL #define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) #define SLIST_FOREACH(var, head, field) \ for((var) = SLIST_FIRST(head); \ (var) != SLIST_END(head); \ (var) = SLIST_NEXT(var, field)) /* * Singly-linked List functions. */ #define SLIST_INIT(head) { \ SLIST_FIRST(head) = SLIST_END(head); \ } #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ (elm)->field.sle_next = (slistelm)->field.sle_next; \ (slistelm)->field.sle_next = (elm); \ } while (0) #define SLIST_INSERT_HEAD(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ (head)->slh_first = (elm); \ } while (0) #define SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (0) #define SLIST_REMOVE(head, elm, type, field) do { \ if ((head)->slh_first == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = (head)->slh_first; \ while( curelm->field.sle_next != (elm) ) \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ } \ } while (0) /* * List definitions. */ #define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LIST_HEAD_INITIALIZER(head) \ { NULL } #define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } /* * List access methods */ #define LIST_FIRST(head) ((head)->lh_first) #define LIST_END(head) NULL #define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) #define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_FOREACH(var, head, field) \ for((var) = LIST_FIRST(head); \ (var)!= LIST_END(head); \ (var) = LIST_NEXT(var, field)) /* * List functions. */ #define LIST_INIT(head) do { \ LIST_FIRST(head) = LIST_END(head); \ } while (0) #define LIST_INSERT_AFTER(listelm, elm, field) do { \ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ (listelm)->field.le_next = (elm); \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } while (0) #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (0) #define LIST_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } while (0) #define LIST_REMOVE(elm, field) do { \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ } while (0) #define LIST_REPLACE(elm, elm2, field) do { \ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ (elm2)->field.le_next->field.le_prev = \ &(elm2)->field.le_next; \ (elm2)->field.le_prev = (elm)->field.le_prev; \ *(elm2)->field.le_prev = (elm2); \ } while (0) /* * Simple queue definitions. */ #define SIMPLEQ_HEAD(name, type) \ struct name { \ struct type *sqh_first; /* first element */ \ struct type **sqh_last; /* addr of last next element */ \ } #define SIMPLEQ_HEAD_INITIALIZER(head) \ { NULL, &(head).sqh_first } #define SIMPLEQ_ENTRY(type) \ struct { \ struct type *sqe_next; /* next element */ \ } /* * Simple queue access methods. */ #define SIMPLEQ_FIRST(head) ((head)->sqh_first) #define SIMPLEQ_END(head) NULL #define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) #define SIMPLEQ_FOREACH(var, head, field) \ for((var) = SIMPLEQ_FIRST(head); \ (var) != SIMPLEQ_END(head); \ (var) = SIMPLEQ_NEXT(var, field)) /* * Simple queue functions. */ #define SIMPLEQ_INIT(head) do { \ (head)->sqh_first = NULL; \ (head)->sqh_last = &(head)->sqh_first; \ } while (0) #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ (head)->sqh_first = (elm); \ } while (0) #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.sqe_next = NULL; \ *(head)->sqh_last = (elm); \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (0) #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ (head)->sqh_last = &(elm)->field.sqe_next; \ (listelm)->field.sqe_next = (elm); \ } while (0) #define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ (head)->sqh_last = &(head)->sqh_first; \ } while (0) /* * Tail queue definitions. */ #define TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ } #define TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first } #define TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ } /* * tail queue access methods */ #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_END(head) NULL #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) /* XXX */ #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) #define TAILQ_EMPTY(head) \ (TAILQ_FIRST(head) == TAILQ_END(head)) #define TAILQ_FOREACH(var, head, field) \ for((var) = TAILQ_FIRST(head); \ (var) != TAILQ_END(head); \ (var) = TAILQ_NEXT(var, field)) #define TAILQ_FOREACH_REVERSE(var, head, field, headname) \ for((var) = TAILQ_LAST(head, headname); \ (var) != TAILQ_END(head); \ (var) = TAILQ_PREV(var, headname, field)) /* * Tail queue functions. */ #define TAILQ_INIT(head) do { \ (head)->tqh_first = NULL; \ (head)->tqh_last = &(head)->tqh_first; \ } while (0) #define TAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ (head)->tqh_first->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (head)->tqh_first = (elm); \ (elm)->field.tqe_prev = &(head)->tqh_first; \ } while (0) #define TAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &(elm)->field.tqe_next; \ } while (0) #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (listelm)->field.tqe_next = (elm); \ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ } while (0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ (elm)->field.tqe_next = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ } while (0) #define TAILQ_REMOVE(head, elm, field) do { \ if (((elm)->field.tqe_next) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = \ (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ } while (0) #define TAILQ_REPLACE(head, elm, elm2, field) do { \ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ (elm2)->field.tqe_next->field.tqe_prev = \ &(elm2)->field.tqe_next; \ else \ (head)->tqh_last = &(elm2)->field.tqe_next; \ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ *(elm2)->field.tqe_prev = (elm2); \ } while (0) /* * Circular queue definitions. */ #define CIRCLEQ_HEAD(name, type) \ struct name { \ struct type *cqh_first; /* first element */ \ struct type *cqh_last; /* last element */ \ } #define CIRCLEQ_HEAD_INITIALIZER(head) \ { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } #define CIRCLEQ_ENTRY(type) \ struct { \ struct type *cqe_next; /* next element */ \ struct type *cqe_prev; /* previous element */ \ } /* * Circular queue access methods */ #define CIRCLEQ_FIRST(head) ((head)->cqh_first) #define CIRCLEQ_LAST(head) ((head)->cqh_last) #define CIRCLEQ_END(head) ((void *)(head)) #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) #define CIRCLEQ_EMPTY(head) \ (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) #define CIRCLEQ_FOREACH(var, head, field) \ for((var) = CIRCLEQ_FIRST(head); \ (var) != CIRCLEQ_END(head); \ (var) = CIRCLEQ_NEXT(var, field)) #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ for((var) = CIRCLEQ_LAST(head); \ (var) != CIRCLEQ_END(head); \ (var) = CIRCLEQ_PREV(var, field)) /* * Circular queue functions. */ #define CIRCLEQ_INIT(head) do { \ (head)->cqh_first = CIRCLEQ_END(head); \ (head)->cqh_last = CIRCLEQ_END(head); \ } while (0) #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ (elm)->field.cqe_prev = (listelm); \ if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ (head)->cqh_last = (elm); \ else \ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ (listelm)->field.cqe_next = (elm); \ } while (0) #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ (elm)->field.cqe_next = (listelm); \ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ (head)->cqh_first = (elm); \ else \ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ (listelm)->field.cqe_prev = (elm); \ } while (0) #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ (elm)->field.cqe_next = (head)->cqh_first; \ (elm)->field.cqe_prev = CIRCLEQ_END(head); \ if ((head)->cqh_last == CIRCLEQ_END(head)) \ (head)->cqh_last = (elm); \ else \ (head)->cqh_first->field.cqe_prev = (elm); \ (head)->cqh_first = (elm); \ } while (0) #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.cqe_next = CIRCLEQ_END(head); \ (elm)->field.cqe_prev = (head)->cqh_last; \ if ((head)->cqh_first == CIRCLEQ_END(head)) \ (head)->cqh_first = (elm); \ else \ (head)->cqh_last->field.cqe_next = (elm); \ (head)->cqh_last = (elm); \ } while (0) #define CIRCLEQ_REMOVE(head, elm, field) do { \ if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ (head)->cqh_last = (elm)->field.cqe_prev; \ else \ (elm)->field.cqe_next->field.cqe_prev = \ (elm)->field.cqe_prev; \ if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ (head)->cqh_first = (elm)->field.cqe_next; \ else \ (elm)->field.cqe_prev->field.cqe_next = \ (elm)->field.cqe_next; \ } while (0) #define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ CIRCLEQ_END(head)) \ (head).cqh_last = (elm2); \ else \ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ CIRCLEQ_END(head)) \ (head).cqh_first = (elm2); \ else \ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ } while (0) #endif /* !_SYS_QUEUE_H_ */ |