ipprobe-mt_rspd.c

00001 /*
00002  * $Id: ipprobe-mt_rspd.c 347265 2009-11-19 13:55:39Z kdickman $
00003  *
00004  * This code is provided as is by Juniper Networks SDK Developer Support.
00005  * It is provided with no warranties or guarantees, and Juniper Networks
00006  * will not provide support or maintenance of this code in any fashion.
00007  * The code is provided only to help a developer better understand how
00008  * the SDK can be used.
00009  *
00010  * Copyright (c) 2009, Juniper Networks, Inc.
00011  * All rights reserved.
00012  *
00013  */
00014 
00022 #include <unistd.h>
00023 #include <errno.h>
00024 #include <string.h>
00025 #include <stdbool.h>
00026 #include <sys/types.h>
00027 #include <sys/queue.h>
00028 #include <sys/socket.h>
00029 #include <isc/eventlib.h>
00030 #include <netinet/in.h>
00031 #include <netinet/in_systm.h>
00032 #include <netinet/ip.h>
00033 #include <netinet/udp.h>
00034 #include <netinet/ip_icmp.h>
00035 #include <arpa/inet.h>
00036 #include <jnx/aux_types.h>
00037 #include <jnx/bits.h>
00038 #include <jnx/patricia.h>
00039 #include <jnx/pconn.h>
00040 #include <jnx/junos_trace.h>
00041 #include "ipprobe-mt.h"
00042 #include IPPROBE_MT_OUT_H
00043 
00044 rspd_mngr_t rspd_mngr;
00045 static LIST_HEAD(, rspd_s)  rspd_list;
00046 
00053 static void
00054 rspd_close (rspd_t *rspd)
00055 {
00056     if (rspd == NULL) {
00057         return;
00058     }
00059 
00060     /* Decrement responder use count. */
00061     if (--rspd->usage > 0) {
00062         /* It's still used by some other client(s). */
00063         return;
00064     }
00065 
00066     if (evTestID(rspd->read_fid)) {
00067         evDeselectFD(rspd->ev_ctx, rspd->read_fid);
00068     }
00069 
00070     /* Close responder socket. */
00071     if (rspd->socket >= 0) {
00072         close(rspd->socket);
00073     }
00074 
00075     /* Remove it from the responder list. */
00076     LIST_REMOVE(rspd, entry);
00077     free(rspd);
00078 
00079     PROBE_TRACE(PROBE_TF_RSPD, "%s: Responder is closed.", __func__);
00080 }
00081 
00094 static void
00095 rspd_pkt_hdlr (evContext lev_ctx UNUSED, void *uap, int fd UNUSED,
00096         int eventmask UNUSED)
00097 {
00098     rspd_t *rspd = (rspd_t *)uap;
00099     probe_pkt_t *pkt = (probe_pkt_t *)rspd->rx_buf;
00100     struct sockaddr_in  src_addr;
00101     probe_pkt_data_t *data;
00102     struct timeval rx_time;
00103     int recv_len = 0;
00104     int send_len = 0;
00105     int addr_len;
00106     bool last_req = false;
00107 
00108     while (!last_req) {
00109         /* Something came in, recode receive time. */
00110         gettimeofday(&rx_time, NULL);
00111         addr_len = sizeof(src_addr);
00112         recv_len = recvfrom(rspd->socket, rspd->rx_buf, PROBE_PKT_SIZE_MAX,
00113                 0, (struct sockaddr *)&src_addr, &addr_len);
00114 
00115         if (recv_len == 0) {
00116             break;
00117         } else if (recv_len < 0) {
00118             if(errno != EAGAIN) {
00119                 PROBE_LOG(LOG_ERR, "%s: Receive probe packet ERROR(%d)!",
00120                         __func__, errno);
00121             }
00122             break;
00123         }
00124 
00125         if (rspd->proto == IPPROTO_UDP) {
00126             data = (probe_pkt_data_t *)rspd->rx_buf;
00127         }  else {
00128             data = &pkt->data;
00129             pkt->header.ip_src.s_addr = 0;
00130             pkt->header.ip_dst.s_addr = src_addr.sin_addr.s_addr;
00131         }
00132 
00133         if (data->type == PROBE_PKT_REQ_LAST) {
00134             last_req = true;
00135         } else if (data->type != PROBE_PKT_REQ) {
00136             PROBE_LOG(LOG_ERR, "%s: Not request packet! type: %d",
00137                     __func__, data->type);
00138             break;
00139         }
00140 
00141         /* Packet has be validated, copy receive time into packet */
00142         bcopy(&rx_time, &data->target_rx_time, sizeof(struct timeval));
00143 
00144         PROBE_TRACE(PROBE_TF_RSPD,
00145                 "%s: Packet type %d, len %d, src_addr %s, src_port %d.",
00146                 __func__, data->type, recv_len, inet_ntoa(src_addr.sin_addr),
00147                 ntohs(src_addr.sin_port));
00148 
00149         data->type = PROBE_PKT_REPLY;
00150         gettimeofday(&data->target_tx_time, NULL);
00151 
00152         send_len = sendto(rspd->socket, rspd->rx_buf, recv_len, 0,
00153                 (struct sockaddr *)&src_addr, addr_len);
00154         if (send_len < 0) {
00155             PROBE_LOG(LOG_ERR, "%s: Send probe packet ERROR(%d)!",
00156                     __func__, errno);
00157             break;
00158         }
00159     }
00160     if (last_req) {
00161         rspd_close(rspd);
00162     }
00163 }
00164 
00171 static int
00172 rspd_open (void)
00173 {
00174     rspd_t *rspd = LIST_FIRST(&rspd_list);
00175     struct sockaddr_in addr;
00176     const int on = 1;
00177 
00178     /* Look for responder with the same protocol and port to reuse. */
00179     while (rspd) {
00180         if ((rspd->proto == rspd_mngr.rx_pkt.proto)
00181                 && (rspd->port == rspd_mngr.rx_pkt.port)) {
00182             rspd->usage++;
00183             if (rspd->timeout < rspd_mngr.rx_pkt.timeout) {
00184                 rspd->timeout = rspd_mngr.rx_pkt.timeout;
00185             }
00186             PROBE_TRACE(PROBE_TF_RSPD, "%s: Reuse responder on protocol %d, "
00187                     "port %d", __func__, rspd->proto, rspd->port);
00188             return 0;
00189         }
00190         rspd = LIST_NEXT(rspd, entry);
00191     }
00192 
00193     /* Create the new responder. */
00194     rspd = calloc(1, sizeof(rspd_t));
00195     INSIST_ERR(rspd);
00196 
00197     rspd->proto = rspd_mngr.rx_pkt.proto;
00198     rspd->port = rspd_mngr.rx_pkt.port;
00199     rspd->timeout = rspd_mngr.rx_pkt.timeout;
00200     rspd->ev_ctx = rspd_mngr.ev_ctx;
00201     rspd->usage++;
00202     LIST_INSERT_HEAD(&rspd_list, rspd, entry);
00203 
00204     if (rspd->proto == IPPROTO_UDP) {
00205         rspd->socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00206         if (rspd->socket < 0) {
00207             PROBE_LOG(LOG_ERR, "%s: Create responder UDP socket ERROR(%d)!",
00208                     __func__, errno);
00209             goto ret_err;
00210         }
00211 
00212         bzero(&addr, sizeof(addr));
00213         addr.sin_family = AF_INET;
00214         addr.sin_port = htons(rspd->port);
00215         addr.sin_addr.s_addr = htonl(INADDR_ANY);
00216         if (bind(rspd->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
00217             PROBE_LOG(LOG_ERR, "%s: Bind responder UDP socket ERROR(%d)!",
00218                     __func__, errno);
00219             goto ret_err;
00220         }
00221         PROBE_TRACE(PROBE_TF_RSPD, "%s: Responder on UDP port %d is opened.",
00222                 __func__, rspd->port);
00223     } else {
00224         rspd->socket = socket(PF_INET, SOCK_RAW, rspd->proto);
00225         if (rspd->socket < 0) {
00226             PROBE_LOG(LOG_ERR, "%s: Create responder RAW socket ERROR(%d)!",
00227                     __func__, errno);
00228             goto ret_err;
00229         }
00230 
00231         if (setsockopt(rspd->socket, IPPROTO_IP, IP_HDRINCL, &on,
00232                 sizeof(on)) < 0) {
00233             PROBE_LOG(LOG_ERR, "%s: Set responder RAW socket option ERROR(%d)!",                    __func__, errno);
00234             goto ret_err;
00235         }
00236         PROBE_TRACE(PROBE_TF_RSPD, "%s: Responder on protocol %d is opened.",
00237                 __func__, rspd->proto);
00238     }
00239 
00240     if (evSelectFD(rspd->ev_ctx, rspd->socket, EV_READ, rspd_pkt_hdlr,
00241             rspd, &rspd->read_fid) < 0) {
00242         PROBE_LOG(LOG_ERR, "%s: evSelectFD responder socket ERROR(%d)!",
00243                 __func__, errno);
00244         goto ret_err;
00245     }
00246 
00247     return 0;
00248 
00249 ret_err:
00250     rspd_close(rspd);
00251     return -1;
00252 }
00253 
00257 static void
00258 rspd_mngr_pkt_hdlr (evContext lev_ctx UNUSED, void *uap UNUSED, int fd,
00259         int eventmask UNUSED)
00260 {
00261     struct sockaddr_in src_addr;
00262     int recv_len = 0;
00263     int addr_len;
00264     rspd_mgmt_pkt_t tx_pkt;
00265 
00266     while (1) {
00267         addr_len = sizeof(src_addr);
00268         recv_len = recvfrom(fd, &rspd_mngr.rx_pkt, sizeof(rspd_mngr.rx_pkt), 0,
00269                 (struct sockaddr *)&src_addr, &addr_len);
00270 
00271         if (recv_len > 0) {
00272             if (recv_len == sizeof(rspd_mgmt_pkt_t)) {
00273                 PROBE_TRACE(PROBE_TF_RSPD,
00274                         "%s: Got probe request, protocol %d, port %d.",
00275                        __func__, rspd_mngr.rx_pkt.proto,
00276                        rspd_mngr.rx_pkt.port);
00277                 rspd_open();
00278                 tx_pkt.type = RSPD_MGMT_MSG_ACK;
00279                 sendto(fd, &tx_pkt, sizeof(tx_pkt), 0,
00280                         (struct sockaddr *)&src_addr, addr_len);
00281             } else {
00282                 PROBE_LOG(LOG_ERR, "%s: Received fragment!", __func__);
00283             }
00284         } else if (recv_len == 0) {
00285             break;
00286         } else if (recv_len < 0) {
00287             if (errno != EAGAIN) {
00288                 PROBE_LOG(LOG_ERR, "%s, Read socket ERROR(%d)!",
00289                         __func__, errno);
00290             }
00291             break;
00292         }
00293     }
00294 }
00295 
00299 void
00300 rspd_mngr_close (void)
00301 {
00302     if (evTestID(rspd_mngr.read_fid)) {
00303         evDeselectFD(rspd_mngr.ev_ctx, rspd_mngr.read_fid);
00304         evInitID(&rspd_mngr.read_fid);
00305     }
00306 
00307     if (rspd_mngr.socket >= 0) {
00308         close(rspd_mngr.socket);
00309         rspd_mngr.socket = -1;
00310     }
00311 
00312     PROBE_TRACE(PROBE_TF_RSPD, "%s: The responder manager is closed.",
00313             __func__);
00314 }
00315 
00324 int
00325 rspd_mngr_open (uint16_t port)
00326 {
00327     struct sockaddr_in addr;
00328 
00329     if (rspd_mngr.socket >= 0) {
00330         if (rspd_mngr.port == port) {
00331             return 0;
00332         } else {
00333             rspd_mngr_close();
00334         }
00335     }
00336     rspd_mngr.port = port;
00337 
00338     evInitID(&rspd_mngr.read_fid);
00339     rspd_mngr.socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00340     if (rspd_mngr.socket < 0) {
00341         PROBE_LOG(LOG_ERR, "%s: Open responder manager socket ERROR(%d)!",
00342                 __func__, errno);
00343         goto ret_err;
00344     }
00345 
00346     bzero(&addr, sizeof(addr));
00347     addr.sin_family = AF_INET;
00348     addr.sin_port = htons(rspd_mngr.port);
00349     addr.sin_addr.s_addr = htonl(INADDR_ANY);
00350     if (bind(rspd_mngr.socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
00351         PROBE_LOG(LOG_ERR, "%s: Bind responder manager socket ERROR(%d)!",
00352                 __func__, errno);
00353         goto ret_err;
00354     }
00355 
00356     if (evSelectFD(rspd_mngr.ev_ctx, rspd_mngr.socket, EV_READ,
00357             rspd_mngr_pkt_hdlr, NULL, &rspd_mngr.read_fid)) {
00358         PROBE_LOG(LOG_ERR, "%s: evSelectFD responder manager socket ERROR(%d)!",
00359                 __func__, errno);
00360         goto ret_err;
00361     }
00362 
00363     PROBE_TRACE(PROBE_TF_RSPD, "%s: The responder manager is open on port %d.",
00364             __func__, rspd_mngr.port);
00365     return 0;
00366 
00367 ret_err:
00368     rspd_mngr_close();
00369     return -1;
00370 }
00371 
00380 int
00381 rspd_mngr_init (evContext lev_ctx)
00382 {
00383     PROBE_TRACE(PROBE_TF_RSPD, "%s: Initialize the responder manager.",
00384             __func__);
00385     bzero(&rspd_mngr, sizeof(rspd_mngr));
00386     rspd_mngr.socket = -1;
00387     rspd_mngr.port = RSPD_MNGR_PORT_DEFAULT;
00388     rspd_mngr.ev_ctx = lev_ctx;
00389 
00390     return 0;
00391 }
00392 

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:27:00 2010 for SDK Your Net Corporation IP Probe MT: ipprobe-mt 1.0 by Doxygen 1.5.1