質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

6954閲覧

自分自身のMACアドレスを取得したい

izuki_y

総合スコア65

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/11/08 02:36

いつもお世話になっております。
件名の事について質問があります。

現在ARPパケットを取得するプログラムを作成しています。
その際に自身のMACアドレスとIPアドレスを送りつける必要があるみたいなので
まず自身のMACアドレスを取得しようとしましたが上手くいきません。

具体的には、ioctlを使ってMACアドレスとを取得しようとするとEINVAL(22)が返ってきます。

環境

  • Windows7 Professional x64(PC)
  • Cygwin 2.0.1
  • clang version 3.5.1

ソース

C

1 2#include <stdio.h> 3 4#include <string.h> 5 6#include <sys/types.h> 7#include <sys/socket.h> 8#include <sys/ioctl.h> 9#include <netinet/in.h> 10#include <net/if.h> 11#include <unistd.h> // for close 12#include <errno.h> 13 14int main(){ 15 16 int fd; 17 struct ifreq ifr; 18 long lReturn = 0; 19 if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ 20 printf("socket errno=%d\n",errno); 21 return 0; 22 } 23 24 ifr.ifr_addr.sa_family = AF_INET; 25 strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1); 26 27 if((lReturn= ioctl(fd, SIOCGIFHWADDR, &ifr)) < 0){ 28 printf("ioctl errno=%d\n",errno); 29 printf("SIOCGIFHWADDR=%lu\n", SIOCGIFHWADDR); 30 printf("ifr pointer=%p\n", &ifr); 31 }else{ 32 printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", 33 (unsigned char)ifr.ifr_hwaddr.sa_data[0], 34 (unsigned char)ifr.ifr_hwaddr.sa_data[1], 35 (unsigned char)ifr.ifr_hwaddr.sa_data[2], 36 (unsigned char)ifr.ifr_hwaddr.sa_data[3], 37 (unsigned char)ifr.ifr_hwaddr.sa_data[4], 38 (unsigned char)ifr.ifr_hwaddr.sa_data[5]); 39 } 40 close(fd); 41 return 0; 42}

[結果]

ioctl errno=22 SIOCGIFHWADDR=2152231785 ifr pointer=0x28cbf0

エラーの詳細を見ると第二引数と第三引数がおかしいみたいですが、
変な所はなさそうですが。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

WindowsならGetAdaptersInfoでも取得できそうです。
http://qiita.com/cielavenir/items/603680454cbec202bdf2

投稿2016/11/08 03:59

ttyp03

総合スコア16996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

izuki_y

2016/11/08 14:57

回答ありがとうございます。 Windowsで開発していますが組込みでPosix系に移植する予定なんです。 せっかく回答していただいたのに申し訳ないです。
guest

0

Windows であれば、GetIfTable API を使ってはどうでしょうか?
GetIfTable function (Windows)

投稿2016/11/08 03:14

qt6hy

総合スコア149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

izuki_y

2016/11/08 14:57

回答ありがとうございます。 Windowsで開発していますが組込みでPosix系に移植する予定なんです。 せっかく回答していただいたのに申し訳ないです。
guest

0

ベストアンサー

Cygwinメーリングリストのとある投稿によると、最近はデバイス名を"eth0"などではなくWindowsのデバイスGUIDで指定する必要があるそうです。また、ioctl(2)以外にgetifaddrs(3)も使えるとのこと。

投稿2016/11/08 05:24

ikedas

総合スコア4227

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

izuki_y

2016/11/08 14:59

回答ありがとうございます。 おっしゃる通り"eth0"では無理でAdapterのIDをを指定する必要がある様でした。 getifaddrsも調べて試してみたいと思います。
guest

0

解決しました。
インターフェース名が"eth0"では駄目の様ですね。
インターフェース名を取得してそれを使ってioctlで SIOCGIFHWADDR を指定すればちゃんと自身のMACアドレスを取得することが出来ました。
人のソースコードを切り張りしただけなので盆雑ですが、ソースも乗っけておきます。

C

1#include <stdio.h> 2#include <string.h> // for memset 3#include <stdlib.h> // for exit 4 5#include <sys/types.h> 6#include <sys/socket.h> 7#include <sys/ioctl.h> 8#include <net/if.h> 9#include <netinet/in.h> 10#include <arpa/inet.h> // resolution waring: `inet_ntoa` is invalid in C99 11#include <unistd.h> // for close 12#include <errno.h> 13 14/* 取得できるインターフェースの最大値 */ 15/* 10個以上インターフェースがある場合は増やしてください */ 16#define MAX_IFR 10 17 18void get_ifinfo(char *devname, struct ifreq *ifreq, int flavor) { 19 20 int iofd; 21 22 if ((iofd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 23 perror("ioctl socket creation"); 24 exit(1); 25 } 26 27 memset(ifreq, '\0', sizeof(*ifreq)); 28 strcpy(ifreq->ifr_name, devname); 29 30 if (ioctl(iofd, flavor, ifreq) < 0) { 31 perror("ioctl"); 32 exit(1); 33 } 34 35 return; 36} 37 38 39int main() 40{ 41 struct ifreq ifr[MAX_IFR]; 42 struct ifconf ifc; 43 int fd; 44 int nifs, i; 45 46 fd = socket(AF_INET, SOCK_DGRAM, 0); 47 48 /* データを受け取る部分の長さ */ 49 ifc.ifc_len = sizeof(ifr); 50 51 /* kernelからデータを受け取る部分を指定 */ 52 ifc.ifc_ifcu.ifcu_buf = (void *)ifr; 53 54 ioctl(fd, SIOCGIFCONF, &ifc); 55 56 /* kernelから帰ってきた数を計算 */ 57 nifs = ifc.ifc_len / sizeof(struct ifreq); 58 59 /* 全てのインターフェース名を表示 */ 60 for (i=0; i<nifs; i++) { 61 struct ifreq ifreq; 62 struct sockaddr_in saddr; 63 64 //IP address 65 get_ifinfo( ifr[i].ifr_name, &ifreq, SIOCGIFADDR); 66 memcpy(&saddr, &(ifreq.ifr_addr), sizeof(saddr)); 67 printf("%s\n", inet_ntoa(saddr.sin_addr)); 68 69 //MAC address 70 get_ifinfo( ifr[i].ifr_name, &ifreq, SIOCGIFHWADDR); 71 printf("%02x:%02x:%02x:%02x:%02x:%02x\n\n", (unsigned char)ifreq.ifr_hwaddr.sa_data[0], (unsigned char)ifreq.ifr_hwaddr.sa_data[1], (unsigned char)ifreq.ifr_hwaddr.sa_data[2], (unsigned char)ifreq.ifr_hwaddr.sa_data[3], (unsigned char)ifreq.ifr_hwaddr.sa_data[4], (unsigned char)ifreq.ifr_hwaddr.sa_data[5]); 72 } 73 74 close(fd); 75 76 return 0; 77}

投稿2016/11/14 15:11

izuki_y

総合スコア65

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問