链路本地地址获取 EUI-48转EUI-64计算 Link local IPv6 Address

本文介绍了如何使用C语言编写程序,通过用户输入的MAC地址(EUI48格式),检查其有效性,然后将其转换为EUI64形式,并进一步生成LinklocalIPv6地址。程序利用正则表达式进行格式验证和地址生成。
摘要由CSDN通过智能技术生成

Enter MAC Address using the following format:
eg. 
1.separate by : -> 0015:2BE4:9B60
2.separate by - -> 00-15-2B-E4-9B-60 
MAC Address(EUI48):00-15-2B-E4-9B-60

EUI64: 02152BFFEFE49B60
Link local IPv6 Address : fe80::0215:2bff:efe4:9b60
 


#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>

//Link local IPv6 Address [EUI-64]

typedef int errno_t;

//functions prototype
bool MAC48_Check(char* MAC48);	// 检测MAC有效性
char* linklocal(char* MAC48);		// 执行EUI48->EUI64转换.生成IPv6链路本地地址
char* regnext(char* content,regex_t* regex);	//获取输入字符串有效部分
char* process(char* ipv6);//将对应IPv6地址转化为小写,去除尾部:

int main(void){
	char* MAC48 = calloc(18,sizeof(char));
	printf("Enter MAC Address using the following format:\neg. \n"
			"1.separate by : -> 0015:2BE4:9B60\n"
			"2.separate by - -> 00-15-2B-E4-9B-60 \n");
	retry:
	printf("MAC Address(EUI48):");
	scanf("%s",MAC48);
	if(!MAC48_Check(MAC48)){
		printf("MAC: %s invalid! Retry\n",MAC48);
		goto retry;
	}
	linklocal(MAC48);
	return 0;
}

bool MAC48_Check(char* MAC48){
	for(int i = 0 ; i < strlen(MAC48) ; i ++){
		MAC48[i] = toupper(MAC48[i]);
	}
	char* pattern = "^([0-9A-F]{4}(:[0-9A-F]{4}){2}|[0-9A-F]{2}(-[0-9A-F]{2}){5})$";
	regex_t regex;
	errno_t state = regcomp(&regex,pattern,REG_EXTENDED);
	if(state){
		char* errbuf = calloc(20,sizeof(char));
		regerror(state,&regex,errbuf,20);
		fprintf(stderr,"Failed to compile Regex: %s\n"
						"Reason:%s\n",pattern,errbuf);
        free(errbuf);
        regfree(&regex);					
		exit(EXIT_FAILURE);
	}
	state = regexec(&regex,MAC48,0,NULL,0);
	regfree(&regex);
	return state != REG_NOMATCH;
}

char* regnext(char* content,regex_t* regex){
	static int position = 0;
	regmatch_t matches[regex->re_nsub + 1];
	errno_t state = regexec(regex,content + position,regex->re_nsub + 1,matches,0);
	if(state == REG_NOMATCH){
		position = 0;
		return NULL;
	}
	char* reval = calloc(matches[0].rm_eo - matches[0].rm_so + 1,sizeof(char));
	memcpy(reval,content + position + matches[0].rm_so,matches[0].rm_eo - matches[0].rm_so);
	position += matches[0].rm_eo;
	return reval;
}


char* linklocal(char* MAC48){
	regex_t regex;
	char* pattern = "[A-E0-9]+";
	errno_t state = regcomp(&regex,pattern,REG_EXTENDED);
	if(state){
		char* errbuf = calloc(20,sizeof(char));
		regerror(state,&regex,errbuf,20);
		fprintf(stderr,"Failed to compile Regex:%s\n"
					   "Reason:%s\n",pattern,errbuf);
		regfree(&regex);
		free(errbuf);
		exit(EXIT_FAILURE);
	}
	//EUI-48 和 EUI-64前24位是OUI
	//EUI-64占64位,转换为十六进制用16个字符表示
	//EUI-48转EUI-64分两个步骤
	//1.在第25位插入11111111 11111110 即 FF FE
	//2.将对应的结果第7位(ul)求异或
	char* EUI64 = calloc(16 + 1,sizeof(char));
	char* EUI48 = calloc(12 + 1,sizeof(char));
	char* value = NULL;
	while((value = regnext(MAC48,&regex)) != NULL){
		strcat(EUI48,value);
		free(value);
	}
	regfree(&regex);
	//step 1.
	memcpy(EUI64,EUI48,6);
	memcpy(EUI64 + 6,"FFEF",4);
	memcpy(EUI64 + 10,EUI48 + 6,6);
	//step 2.
	char ul = EUI64[1];
	ul = (ul >= 'A' && ul <= 'F') ? 10 + ul - 'A' : ul - '0';
	ul ^= 2;
	EUI64[1] = (ul >= 0 && ul <= 9) ? ul + '0' : ul - 10 + 'A';
	printf("\nEUI64: %s\n",EUI64);
	char* reval = calloc(23,sizeof(char)); //返回的链路本地地址字符串最长22个字节
	strcat(reval,"fe80::");
	pattern = "[0-9A-F]{4}";
	state = regcomp(&regex,pattern,REG_EXTENDED);
	if(state){
		char* errbuf = calloc(20,sizeof(char));
		regerror(state,&regex,errbuf,20);
		fprintf(stderr,"Failed to compile Regex:%s\n"
					   "Reason:%s\n",pattern,errbuf);
		free(errbuf);
		regfree(&regex);
		exit(EXIT_FAILURE);
	}
	while((value = regnext(EUI64,&regex)) != NULL){
		strcat(reval,value);
		strcat(reval,":");
		free(value);
	}
	
	regfree(&regex);
	
	reval = process(reval);
	
	printf("Link local IPv6 Address : %s\n",reval);
	return reval;
}

char* process(char* ipv6){
	ipv6[strlen(ipv6) - 1] = '\0';//去除尾部分号
	for(int i = 0 ; i < strlen(ipv6) ; i ++){//将IPv6地址转化为小写
		ipv6[i] = tolower(ipv6[i]);
	}
	return ipv6;

}












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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值