免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2834 | 回复: 0
打印 上一主题 下一主题

Linux下添加/删除路由 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-10-25 00:24 |只看该作者 |倒序浏览
以下代码改自net-tools相关代码:

#include <asm/types.h>;
#include <sys/param.h>;
#include <sys/types.h>;
#include <sys/socket.h>;
#include <netinet/in.h>;
#include <arpa/inet.h>;
#include <arpa/nameser.h>;
#include <net/route.h>; /* realy broken */
#include <sys/ioctl.h>;
#include <ctype.h>;
#include <errno.h>;
#include <netdb.h>;
#include <resolv.h>;
#include <unistd.h>;
#include <stdlib.h>;
#include <string.h>;
#include <stdio.h>;

/************************************************************/
#define RTACTION_ADD   1
#define RTACTION_DEL   2
#define RTACTION_HELP  3

#define E_OPTERR        3
#define E_USAGE                4
#define E_SOCK                5
#define E_LOOKUP        6

/* Keep this in sync with /usr/src/linux/include/linux/route.h */
#define RTF_UP          0x0001          /* route usable                 */
#define RTF_GATEWAY     0x0002          /* destination is a gateway     */
#define RTF_HOST        0x0004          /* host entry (net otherwise)   */

#define mask_in_addr(x) (((struct sockaddr_in *)&((x).rt_genmask))->;sin_addr.s_addr)
#define full_mask(x) (x)

/*
#define mask_in_addr(x) ((x).rt_genmask)
#define full_mask(x) (((struct sockaddr_in *)&(x))->;sin_addr.s_addr)
*/
int usage(void)
{
    fprintf(stderr, "Usage: inet_route [-vF] del {-host|-net} Target[/prefix] [gw Gw] [metric M] [[dev] If]\n";
    fprintf(stderr, "       inet_route [-vF] add {-host|-net} Target[/prefix] [gw Gw] [metric M]\n";
    fprintf(stderr, "                              [netmask N] [mss Mss] [window W] [irtt I]\n";
    fprintf(stderr, "                              [mod] [dyn] [reinstate] [[dev] If]\n";
    fprintf(stderr, "       inet_route [-vF] add {-host|-net} Target[/prefix] [metric M] reject\n";
    fprintf(stderr, "       inet_route [-FC] flush      NOT supported\n";
    return (E_USAGE);
}


/* Like strncpy but make sure the resulting string is always 0 terminated. */
char * safe_strncpy(char *dst, const char *src, size_t size)
{
        dst[size-1] = '\0';
        return strncpy(dst, src, size-1);
}

int INET_getsock(char *bufp, struct sockaddr *sap)
{
    char *sp = bufp, *bp;
    unsigned int i;
    unsigned val;
    struct sockaddr_in *sin;

    sin = (struct sockaddr_in *) sap;
    sin->;sin_family = AF_INET;
    sin->;sin_port = 0;

    val = 0;
    bp = (char *) &amp;
    for (i = 0; i < sizeof(sin->;sin_addr.s_addr); i++) {
        *sp = toupper(*sp);

        if ((*sp >;= 'A') && (*sp <= 'F'))
            bp |= (int) (*sp - 'A') + 10;
        else if ((*sp >;= '0') && (*sp <= '9'))
            bp |= (int) (*sp - '0');
        else
            return (-1);

        bp <<= 4;
        sp++;
        *sp = toupper(*sp);

        if ((*sp >;= 'A') && (*sp <= 'F'))
            bp |= (int) (*sp - 'A') + 10;
        else if ((*sp >;= '0') && (*sp <= '9'))
            bp |= (int) (*sp - '0');
        else
            return (-1);

        sp++;
    }
    sin->;sin_addr.s_addr = htonl(val);

    return (sp - bufp);
}

int INET_resolve(char *name, struct sockaddr_in *sin, int hostfirst)
{
    struct hostent *hp;
    struct netent *np;

    /* Grmpf. -FvK */
    sin->;sin_family = AF_INET;
    sin->;sin_port = 0;

    /* Default is special, meaning 0.0.0.0. */
    if (!strcmp(name, "default") {
        sin->;sin_addr.s_addr = INADDR_ANY;
        return (1);
    }
    /* Look to see if it's a dotted quad. */
    if (inet_aton(name, &sin->;sin_addr)) {
        return 0;
    }
    /* If we expect this to be a hostname, try hostname database first */
    if (hostfirst &&
        (hp = gethostbyname(name)) != (struct hostent *) NULL) {
        memcpy((char *) &sin->;sin_addr, (char *) hp->;h_addr_list[0],
                sizeof(struct in_addr));
        return 0;
    }
    /* Try the NETWORKS database to see if this is a known network. */
    if ((np = getnetbyname(name)) != (struct netent *) NULL) {
        sin->;sin_addr.s_addr = htonl(np->;n_net);
        return 1;
    }
    if (hostfirst) {
        /* Don't try again */
        errno = h_errno;
        return -1;
    }

    if ((hp = gethostbyname(name)) == (struct hostent *) NULL) {
        errno = h_errno;
        return -1;
    }
    memcpy((char *) &sin->;sin_addr, (char *) hp->;h_addr_list[0],
           sizeof(struct in_addr));

    return 0;
}

int INET_input(int type, char *bufp, struct sockaddr *sap)
{
    switch (type) {
    case 1:
        return (INET_getsock(bufp, sap));
    case 256:
        return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
    default:
        return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
    }
}

int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
{
    struct sockaddr_in *mask = (struct sockaddr_in *) m;
    char *slash, *end;
    int prefix;

    if ((slash = strchr(adr, '/')) == NULL)
        return 0;

    *slash++ = '\0';
    prefix = strtoul(slash, &end, 0);
    if (*end != '\0')
        return -1;

    if (name) {
        sprintf(name, "/%d", prefix);
    }
    mask->;sin_family = AF_INET;
    mask->;sin_addr.s_addr = htonl(~(0xffffffffU >;>; prefix));
    return 1;
}

int INET_setroute(int action, int options, char **args)
{
    struct rtentry rt;
    char target[128], gateway[128] = "NONE", netmask[128] = "default";
    int xflag, isnet,skfd;

    xflag = 0;

    if (!strcmp(*args, "-net") {
        xflag = 1;
        args++;
    } else if (!strcmp(*args, "-host") {
        xflag = 2;
        args++;
    }
    if (*args == NULL)
        return (usage());

    safe_strncpy(target, *args++, (sizeof target));

    /* Clean out the RTREQ structure. */
    memset((char *) &rt, 0, sizeof(struct rtentry));

    /* Special hack for /prefix syntax */
    {
        union {
            struct sockaddr_in m;
            struct sockaddr d;
        } mask;
        int n;

        n = INET_getnetmask(target, &mask.d, netmask);
        if (n < 0)
            return usage();
        else if (n)
            rt.rt_genmask = full_mask(mask.d);
    }

    /* Prefer hostname lookup is -host flag was given */
    if ((isnet = INET_input((xflag!=2? 0: 256), target, &rt.rt_dst)) < 0) {
        return (1);
    }
    switch (xflag) {
    case 1:
       isnet = 1; break;
    case 2:
       isnet = 0; break;
    default:
        break;
    }

    /* Fill in the other fields. */
    rt.rt_flags = (RTF_UP | RTF_HOST);
    if (isnet)
        rt.rt_flags &= ~RTF_HOST;

    while (*args) {
        if (!strcmp(*args, "netmask") {
            struct sockaddr mask;

            args++;
            if (!*args || mask_in_addr(rt))
                return (usage());
            safe_strncpy(netmask, *args, (sizeof netmask));
            if ((isnet = INET_input(0, netmask, &mask)) < 0) {
                return (E_LOOKUP);
            }
            rt.rt_genmask = full_mask(mask);
            args++;
            continue;
        }
        if (!strcmp(*args, "gw") || !strcmp(*args, "gateway")) {
            args++;
            if (!*args)
                return (usage());
            if (rt.rt_flags & RTF_GATEWAY)
                return (usage());
            safe_strncpy(gateway, *args, (sizeof gateway));
            if ((isnet = INET_input(256, gateway, &rt.rt_gateway)) < 0) {
                return (E_LOOKUP);
            }
            if (isnet) {
                fprintf(stderr, "route: %s: cannot use a NETWORK as gateway!\n",gateway);
                return (E_OPTERR);
            }
            rt.rt_flags |= RTF_GATEWAY;
            args++;
            continue;
        }
    }

    /* sanity checks.. */
    if (mask_in_addr(rt)) {
        __u32 mask = ~ntohl(mask_in_addr(rt));
        if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) {
            fprintf(stderr, "route: netmask %.8x doesn't make sense with host route\n", mask);
            return (E_OPTERR);
        }
        if (mask & (mask + 1)) {
            fprintf(stderr, "route: bogus netmask %s\n", netmask);
            return (E_OPTERR);
        }
        mask = ((struct sockaddr_in *) &rt.rt_dst)->;sin_addr.s_addr;
        if (mask & ~mask_in_addr(rt)) {
            fprintf(stderr, "route: netmask doesn't match route address\n");
            return (E_OPTERR);
        }
    }
    /* Fill out netmask if still unset */
    if ((action == RTACTION_ADD) && rt.rt_flags & RTF_HOST)
        mask_in_addr(rt) = 0xffffffff;

    /* Create a socket to the INET kernel. */
    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        return (E_SOCK);
    }
    /* Tell the kernel to accept this route. */
    if (action == RTACTION_DEL) {
        if (ioctl(skfd, SIOCDELRT, &rt) < 0) {
            perror("SIOCDELRT");
            close(skfd);
            return (E_SOCK);
        }
    } else {
        if (ioctl(skfd, SIOCADDRT, &rt) < 0) {
            perror("SIOCADDRT");
            close(skfd);
            return (E_SOCK);
        }
    }

    /* Close the socket. */
    (void) close(skfd);
    return (0);
}

int route_edit(int action, int options, char **argv)
{
    return (INET_setroute(action, options, argv));
}

int main(int argc,char **argv)
{
        int what,options,i;
       
        what=0;
        if(argc<3)
        {
                printf("argc<3\n");
                return 0;
        }
        argc--;
        argv++;
       
        if (!strcmp(*argv, "add"))
                what = RTACTION_ADD;
        else if (!strcmp(*argv, "del") || !strcmp(*argv, "delete"))
                what = RTACTION_DEL;
               
        i = route_edit(what, options, ++argv);
        if (i == E_OPTERR)
                usage();

        return (i);
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP