用C语言制作cgi程序修改linux debian11 ip地址

9 篇文章 0 订阅
2 篇文章 0 订阅

本文的运行环境是上一篇博客中搭建的apache2 cgi

cgi程序与普通的c语言程序几乎没啥区别,只是要注意以下几点:

1. 如果程序中需要执行root权限的命令,比如systemctl,需要将apache2的用户www-data设置成免输密码的sudoers,然后在程序中使用sudo systemctl 来运行

2. 获取apache传来的query string的方法是 getenv("QUERY_STRING")

3. cgi程序按照apache的要求必须先输出content-type

4. 标准输出将作为http request的返回结果

下面是一个修改debian11 ip地址的c语言cgi程序,因为用到了systemctl命令,所以要将www-data赋予root权限才能执行

/*
cd ~/code/ChangeIP/ && gcc main.c -o ChangeIP && sudo cp ChangeIP /var/www/cgi/changeip.cgi && cd /var/www/cgi && sudo chmod 777 changeip.cgi && ./changeip.cgi
*/



#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<net/if.h>
#include<netinet/in.h>
#include<string.h>
#include<signal.h>
#include<sys/wait.h>
#include<sys/ioctl.h>
#include<regex.h>


#define NameMaxLen 99

int get_all_networkcards(int first, char* first_card_name);
char* get_ip(char* ETH_NAME, char* ip);

int main(int argc, char** args)
{

  const char* interfaces_path_edit = "/var/www/cgi/interfaces";
  const char* interfaces_path = "/etc/network/interfaces";

  char* new_ip = 0; int new_ip_len = 0; char new_ip_pre[16]; int new_ip_pre_ok = 0;
  char first_card_name[NameMaxLen + 1];  char ip[100];
  FILE* fd; char cp_cmd[1000];

  printf("Content-type:text/html\r\n\r\n<br>\r\n-------change ip-----------<br>\r\n"); // required by cgi, a blank line must after the first line
  if (argc > 1) { new_ip = args[1];  printf("args[1]=%s, argc=%d<br>\r\n", args[1], argc); }
  else if (getenv("QUERY_STRING")) { new_ip = getenv("QUERY_STRING"); printf("query_string=%s<br>\r\n", new_ip); }
  else goto invalid_new_ip;
  if (new_ip == NULL) { goto invalid_new_ip; } printf("received new ip = %s<br>\r\n", new_ip);
  new_ip_len = strlen(new_ip); if (new_ip_len < 7 || new_ip_len>15) { goto invalid_new_ip; }
  strcpy(new_ip_pre, new_ip);
  for (int i = new_ip_len - 1; i > 0; i--)
  {
    if (new_ip_pre[i] == '.') { new_ip_pre[i + 1] = 0; new_ip_pre_ok = 1; break; }
  }
  if (!new_ip_pre_ok) { goto invalid_new_ip; } printf("new ip pre: %s<br>\r\n", new_ip_pre);


  if (get_all_networkcards(1, first_card_name) < 0) { printf("cannot find a netword card<br>\r\n"); return 0; }
  printf("network card name: %s<br>\r\n", first_card_name);


  if (get_ip(first_card_name, ip)) printf("current ip=%s<br>\r\n", ip);
  remove(interfaces_path_edit);
  fd = fopen(interfaces_path_edit, "w"); if (fd == NULL) { printf("cannot open file %s to write<br>\r\n", interfaces_path_edit);   return 0; }
  fprintf(fd, "auto "); fprintf(fd, first_card_name); fprintf(fd, "\n");
  fprintf(fd, "iface "); fprintf(fd, first_card_name); fprintf(fd, " inet static\n");
  fprintf(fd, "address "); fprintf(fd, new_ip); fprintf(fd, "\n");
  fprintf(fd, "netmask 255.255.255.0\n");
  fprintf(fd, "gateway "); fprintf(fd, new_ip_pre); fprintf(fd, "1\n");
  fprintf(fd, "network "); fprintf(fd, new_ip_pre); fprintf(fd, "0\n");
  fprintf(fd, "broadcase "); fprintf(fd, new_ip_pre); fprintf(fd, "255\n");
  fflush(fd); fclose(fd);
  strcpy(cp_cmd, "sudo cp ");  strcat(cp_cmd, interfaces_path_edit); strcat(cp_cmd, " "); strcat(cp_cmd, interfaces_path); printf("%s<br>\r\n", cp_cmd);
  system(cp_cmd); printf("updated config file\n");
  usleep(10000);// sleep for 10 ms, wait for file copy complete
  system("sudo systemctl restart networking &");
  printf("update ip address succeed, new ip: %s<br>\r\n", new_ip); return 0;

invalid_new_ip: printf("invalid new ip<br>\r\n");  return 0;
}


int get_all_networkcards(int first, char* first_card_name)
{
  struct ifreq ifr;
  struct ifconf ifc;
  char buf[2048];
  int success = 0;

  int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
  if (sock == -1) {
    printf("socket error\n");
    return -1;
  }

  ifc.ifc_len = sizeof(buf);
  ifc.ifc_buf = buf;
  if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
    printf("ioctl error\n");
    return -1;
  }

  struct ifreq* it = ifc.ifc_req;
  const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
  char szMac[64];
  int count = 0;
  for (; it != end; ++it)
  {
    strcpy(ifr.ifr_name, it->ifr_name);
    if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0)
    {
      if (ifr.ifr_flags & IFF_LOOPBACK) continue; // don't count loopback
      if (ioctl(sock, SIOCGIFHWADDR, &ifr)) continue;
      count++;
      if (first)
      {
        if (strlen(ifr.ifr_name) < NameMaxLen) { strcpy(first_card_name, ifr.ifr_name); return 1; }
        else { printf("card name too long\n"); return -1; }
      }
      else
      {
        unsigned char* ptr;
        ptr = (unsigned char*)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0];
        snprintf(szMac, 64, "%02X:%02X:%02X:%02X:%02X:%02X", *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3), *(ptr + 4), *(ptr + 5));
        printf("%d. Interface name : %s , Mac address : %s \n", count, ifr.ifr_name, szMac);
      }
    }
    else
    {
      printf("get mac info error\n");
      return -1;
    }
  }
  if (first) { printf("no card found\n"); return -1; }
  return 1;
}


/*************************************************************
* 函数功能:    通过正则表达式检测是否为IP地址
* 参数类型:    需要检测的IP地址
* 返回类型:    成功返回0,失败返回-1
**************************************************************/
int check_right_ip(const char* ip)
{
  int status = 0;
  int cflags = REG_EXTENDED;
  regmatch_t pmatch[1];
  const size_t nmatch = 1;
  regex_t reg;
  char str_ip[30] = "";
  const char* pattern = "[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}";//存在局限

  strcpy(str_ip, ip);
  regcomp(&reg, pattern, cflags);
  status = regexec(&reg, str_ip, nmatch, pmatch, 0);

  if (status == REG_NOMATCH)
  {
    printf("No match\n");
    return -1;
  }
  else if (status == 0)
  {
    return 0;
  }
  regfree(&reg);

  return 0;
}

/*************************************************************
* 函数功能:    获取IP地址
* 参数类型:    IP地址存放位置
* 返回类型:
**************************************************************/
char* get_ip(char* ETH_NAME, char* ip)
{
  int sock;
  struct sockaddr_in sin;
  struct ifreq ifr;
  char* temp_ip = NULL;

  sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock == -1)
  {
    perror("socket");
    return NULL;
  }
  strncpy(ifr.ifr_name, ETH_NAME, IFNAMSIZ - 1);
  ifr.ifr_name[IFNAMSIZ - 1] = 0;

  if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)
  {
    perror("ioctl");
    return NULL;
  }

  memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
  temp_ip = inet_ntoa(sin.sin_addr);
  strcpy(ip, temp_ip);
  fprintf(stdout, "eth0: %s\n", temp_ip);

  return ip;
}

/*************************************************************
* 函数功能:    手动设置IP地址
* 参数类型:    要设置的IP地址
* 返回类型:    成功返回0,失败返回-1
**************************************************************/
int set_hand_ip(const char* ipaddr, char* ETH_NAME)
{
  int sock_set_ip;
  struct sockaddr_in sin_set_ip;
  struct ifreq ifr_set_ip;

  memset(&ifr_set_ip, 0, sizeof(ifr_set_ip));
  if (ipaddr == NULL)
  {
    return -1;
  }

  sock_set_ip = socket(AF_INET, SOCK_STREAM, 0);
  //printf("sock_set_ip=====%d\n",sock_set_ip);
  if (sock_set_ip < 0)
  {
    perror("socket create failse...SetLocalIp!");
    return -1;
  }

  memset(&sin_set_ip, 0, sizeof(sin_set_ip));
  strncpy(ifr_set_ip.ifr_name, ETH_NAME, sizeof(ifr_set_ip.ifr_name) - 1);

  sin_set_ip.sin_family = AF_INET;
  sin_set_ip.sin_addr.s_addr = inet_addr(ipaddr);
  memcpy(&ifr_set_ip.ifr_addr, &sin_set_ip, sizeof(sin_set_ip));
  printf("ipaddr===%s\n", ipaddr);
  if (ioctl(sock_set_ip, SIOCSIFADDR, &ifr_set_ip) < 0)
  {
    perror("Not setup interface");
    return -1;
  }

  //设置激活标志
  ifr_set_ip.ifr_flags |= IFF_UP | IFF_RUNNING;

  //get the status of the device
  if (ioctl(sock_set_ip, SIOCSIFFLAGS, &ifr_set_ip) < 0)
  {
    perror("SIOCSIFFLAGS");
    return -1;
  }

  close(sock_set_ip);
  return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuzen

您的资助将帮助我创作更好的作品

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值