2016-03-15 141 views
-1

我使用这行代码作为打印Linux上接口的IP地址的代码段的最后一部分。检查它是否为空

printf ("%s\n", inet_ntoa (((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr)); 

这很好,但如果我不输入接口名称作为参数,我会得到分段错误。

有没有一种方法来检查,如果这个代码:

inet_ntoa (((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr) 

已与参数提供或不?谢谢。

以下是上下文的完整源代码。

/* 
* This program is free software: you can redistribute it and/or modify 
* it under the terms of the GNU General Public License as published by 
* the Free Software Foundation, either version 3 of the License, or 
* (at your option) any later version. 
* 
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
* GNU General Public License for more details. 
* 
* You should have received a copy of the GNU General Public License 
* along with this program. If not, see <http://www.gnu.org/licenses/>. 
*/ 

/******************************************************************** 
* Description: 
* Author: John Cartwright <> 
* Created at: Wed Jan 13 11:44:29 AEDT 2016 
* Computer: ubuntu 
* System: Linux 4.3.0-5-generic on x86_64 
* 
* Copyright (c) 2016 John Cartwright,,, All rights reserved. 
* 
********************************************************************/ 

#include <linux/kernel.h>  /* for struct sysinfo */ 
#include <sys/sysinfo.h>  /* For the sysinfo struct. */ 
#include <stdio.h> 
#include <string.h>  /* for strncpy */ 
#include <unistd.h>  /* for close */ 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <netinet/in.h> 
#include <net/if.h> 
#include <stdlib.h> /* For the system() function. */ 
#include <arpa/inet.h> 

#include "info.h" 

#define BUF 0x05 

int main (int argc, char **argv) 
{ 
    int fd; 
    struct ifreq ifr; 
    char *myarg1 = argv[2]; 
    char hostname[128]; 
    char *iface = myarg1; 
    unsigned char *mac; 
    char command[50]; 

    if (argv[1] == NULL) 
    { 
     printf ("********************************************\n"); 
     printf ("*   Simple system information.  *\n"); 
     printf ("*           *\n"); 
     printf ("* IP info: --ip <IFACE>     *\n"); 
     printf ("* Print ARP table: --arp     *\n"); 
     printf ("* Print sys info: --system     *\n"); 
     printf ("********************************************\n"); 
     printf ("\nThe PID of this program was: %i\n", getpid()); 
    } 

    /* Getting information about the routing table. */ 

    if (argc > 1 && strncmp (argv[1], "--arp", BUF) == 0) 
    { 
     printf ("This is the routing table.\n"); 
     char *arg[] = { "cat", "/proc/net/arp", NULL }; 
     execvp (arg[0], arg); 
    } 

    if (argc > 1 && strncmp (argv[1], "--system", BUF) == 0) 
    { 
     information(); 
    } 


    if (argc > 1 && strncmp (argv[1], "--hostname", BUF) == 0) 
    { 
     gethostname(hostname, sizeof hostname); 
     printf("Hostname: %s\n", hostname); 
    } 

    if (argc > 1 && strncmp (argv[1], "--ip", BUF) == 0) 
    { 
     // This code from: http://www.binarytides.com/c-program-to-get-mac-address-from-interface-name-on-linux/ 
     FILE *f; 
     char line[100] , *p , *c; 
     char myip; 

     f = fopen("/proc/net/route" , "r"); 

     while(fgets(line , 100 , f)) 
     { 
      p = strtok(line , " \t"); 
      c = strtok(NULL , " \t"); 

      if(p!=NULL && c!=NULL) 
      { 
       if(strcmp(c , "00000000") == 0) 
       { 
        printf("Default interface is : %s \n" , p); 
        break; 
       } 
      } 
     } 

     fd = socket(AF_INET, SOCK_DGRAM, 0); 

     ifr.ifr_addr.sa_family = AF_INET; 
     strncpy(ifr.ifr_name , iface , IFNAMSIZ-1); 

     ioctl(fd, SIOCGIFHWADDR, &ifr); 

     close(fd); 

     mac = (unsigned char *)ifr.ifr_hwaddr.sa_data; 

     //display mac address 
     printf("Mac : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n" , mac[0], mac[1], mac[2], \ 
     mac[3], mac[4], mac[5]); 

     fd = socket (AF_INET, SOCK_DGRAM, 0); 
     /* I want to get an IPv4 IP address */ 
     ifr.ifr_addr.sa_family = AF_INET; 

     /* I want IP address attached to the specified interface. */ 
     strncpy (ifr.ifr_name, myarg1, IFNAMSIZ - 1); 

     ioctl (fd, SIOCGIFADDR, &ifr); 

     close (fd); 

     // End binarytides code. 

     /* display result */ 
     printf ("IP information.\n"); 
     printf("Gateway IP:\n"); 

     strcpy(command, "/sbin/ip route | awk '/default/ { print $3 }'"); 
     system(command); 

     printf("IP address:\n"); 
     printf ("%s\n", inet_ntoa (((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr)); 
    } 

    return 0; 
} 
+4

你真正的问题是“我怎么知道,如果'的ioctl(FD,SIOCGIFADDR,&ifr);'成功了吗?”要回答这个问题,阅读文档'ioctl'。 –

+1

另外你使用'strncpy'不正确,必须空值终止缓冲区 –

+2

一般而言,如代码中的许可条款在堆栈溢出时并不适用 –

回答

0

我怀疑的问题是,sin_add为NULL,但被dereferenced,这是导致该段做错了什么。

就像M.M所建议的那样,从这里向后倒退。

0

你的问题应该是我怎么知道我已经指定的命令名称后至少2个参数:

变化argc > 1argc >= 3。然后参数是您的程序名称,"--ip"和接口名称?

if (argc >= 3 && strncmp (argv[1], "--ip", BUF) == 0) 

否则,您可以执行该程序为programname --ip将与SIGSEGV崩溃。这不是你问的吗?

+0

......或者他有太多的咖啡因和糖;-) – Olaf