반응형

1. 동작중인 프로세스 디버깅 실행방법

 

-    "gdb [프로세스 경로를 포함한 파일명 ] [프로세스 번호]"를 입력한다.

-    디버깅하고자 하는 프로그램이 동작이 되지 않으면 "continue"를 입력한다.

 

#gdb /root/kkk 134

...

어쩌구 저쩌구..

...

..

(gdb) continue

 

 

2. 죽는 위치 확인

- bt를 입력하면 segment fault 발생한 위치를 보여줌

- list를 입력하면 segment fault 발생한 소스 파일을 알려줌

- printf 변수명을 입력하면 변수의 값을 출력할 수 있음

 

(gdb)bt

...

어쩌구 저쩌구..

...

..

 

(gdb)list

- 위치 메시지 출력

 

(gdb) printf "%p" pointer
- printf와 동일함.

- 죽은 위치에서 유효한 변수만 출력됨.

 

 

 

3. 도움말

-    help 명령어 입력하면 명령어 도움말을 볼 수 있음

 

(gdb) help printf
printf "printf format string", arg1, arg2, arg3, ..., argn
This is useful for formatted output in user-defined commands.

 

 

https://brunch.co.kr/@alden/13

 

gdb를 이용해 메모리 덤프 뜨기

Linux Performance | 이번 글에서는 gdb를 이용해 메모리 덤프를 생성하는 방법을 살펴보겠습니다. 사실 많이 활용되지는 않지만, 메모리 관련된 이슈가 있을 때 사용하면 꽤 많은 도움을 받을 수 있기

brunch.co.kr

https://sonseungha.tistory.com/454

 

[gdb] The GNU Debugger : 3. Stack 정보 분석하기

스택은 현재 프로세스가 실행 중인 코드가 어디인지 확인할 수 있기에 매우 중요한 정보라고 할 수 있습니다. gdb에서는 종료되지 않은 함수를 하나의 frame이라고 합니다. 각 프레임은 스택에 쌓

sonseungha.tistory.com

https://jeonjun930.tistory.com/21

 

디버거 GDB 사용법

1. 디버거 사용법: GDB (콘솔상에서 사용하는 디버거) - bug : 프로그램에 존재하는 잠재적인 오류 - de-bugging : 버그를 찾는 행위 - de-bugger : 버그를 찾는데 도와주는 도구 일반 사용자 shell(user)가 메

jeonjun930.tistory.com

https://bpsecblog.wordpress.com/2016/04/04/gdb_memory_2/

 

우리집에 GDB 있는데… 메모리 보고갈래?(2)

season 1. 우리집에 GDB 있는데… 메모리 보고 갈래?(2) Day #2. 애프터 신청 (너 gdb 사용법, 갖고싶다.. 너란 stack )   in09@ubuntu:~/bpsecblog/day2$ gcc -fno-stack-protector -o tomato tomato.c -fno-stack-protector 옵션을 포

bpsecblog.wordpress.com

https://htst.tistory.com/66

 

변수의 메모리 배치 확인 및 GDB 사용법

변수의 메모리 배치 확인 및 GDB 사용법에 대해서 ■ 사용시스템 HackMe(ID/PASS: level9/apple) 1. 변수의 메모리 배치 변수의 메모리 배치를 확인하기 위해서 프로그램을 만들어 보자. [level9@ftz level9]$ ls.

htst.tistory.com

http://psyoblade.egloos.com/2653919

 

gdb 를 통한 디버깅 따라하기

 

psyoblade.egloos.com

http://egloos.zum.com/psyoblade/v/2653919

 

gdb 를 통한 디버깅 따라하기

참고서적 : 유닉스 리눅스 프로그래밍 필수 유틸리티 : vi, make, gcc, gdb, cvs, rpm1. 우선 컴파일 시에 디버깅 정보를 담아야 한다. gcc -g -o [프로그램명] [소스파일명] 디버깅 옵션인 -g 으로 컴파일하

egloos.zum.com

https://blog.daum.net/yesiam1/48

 

리눅스 컴파일 과정과 gcc 옵션, 그리고 라이브러리 만들기

gcc 컴파일 과정 1) 전처리 단계   소스파일=file.c -> (전처리=cpp) -> 전처리된 파일=file.i   전처리기(cpp) = gcc 의 가장 먼저 작동됨, cpp는 소스 파일의 #include #define으로 시작되는 전처리기 부분..

blog.daum.net

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=cronuskim&logNo=40044981841

 

메모리 누수 탐지, 디버깅 방법 정리

출처: http://wiki.liebmona.net/wiki.php/%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%88%84%EC%88%...

blog.naver.com

https://terrorjang.tistory.com/5

 

gdb 기초 사용법

gdb를 사용해야 할 일이 많아서 내가 사용하기에 맞게끔 정리를 해야겠다 인터넷을 뒤지다 보면 컴파일할때부터 gcc -g 옵션을 가지고 컴파일한 파일 위주로 설명이 되어 있다 나는 그렇게 컴파일

terrorjang.tistory.com

https://m.blog.naver.com/wwwkasa/221214943293

 

리눅스 디버거 gdb 사용법

먼저 gdb 사용시 가장 자주 사용하는 명령어를 요약 정리하고 아래쪽에서 실제 샘플 프로그램을 작성후 디...

blog.naver.com

https://blog.naver.com/so_ojin0914/222212181012

 

[디바이스 드라이버 Ⅰ] GDB 디버거

GDB란? - GDB는 GNU에서 만든 매우 강력한 디버거이다. - GDB는 CLI(명령라인 인터페이스)...

blog.naver.com

 

'OS > LINUX' 카테고리의 다른 글

리눅스 로그 표시 제거  (0) 2018.01.03
리눅스 라이브러리 생성(동적,정적)  (0) 2017.10.12
리눅스 폴더 복사 이동 삭제  (0) 2017.03.21
리눅스 명령어  (0) 2016.10.13
find, grep 사용법  (0) 2016.08.12
반응형
출처: http://zetawiki.com/wiki/%EB%A6%AC%EB%88%85%EC%8A%A4%EC%97%90%EC%84%9C_%ED%8F%B4%EB%8D%94_%ED%86%B5%EC%A7%B8%EB%A1%9C_%EB%B3%B5%EC%82%AC%ED%95%98%EA%B8%B0
 
리눅스 폴더 복사
리눅스 폴더 전체 복사
리눅스에서 폴더 통째로 복사하기
유닉스 계통에서 폴더 통째로 복사하기


[복사]

  • 원본폴더를 통째로(즉 하위폴더 및 파일들을 포함하여) 목적지폴더로 복사할 수 있다.
  • 상황에 따라 하위로 복사되거나, 폴더명이 바뀌며 복사된다.
  • 목적지폴더가 원본폴더의 상위폴더가 될 것인지, 아니면 원본폴더의 다른이름이 될 것인지는 상황에 따라 다르므로 주의가 필요하다.
  • 맨뒤에 '/'를 붙이든 말든 결과에는 상관이 없다. ★

[명령어]
cp -r 원본폴더 목적지폴더
cp -r 원본폴더 목적지폴더/
cp -r 원본폴더/ 목적지폴더
cp -r 원본폴더/ 목적지폴더/
[예시]
cp -r a /test/b
cp -r a /test/b/
cp -r a/ /test/b
cp -r a/ /test/b/
  • /test 폴더가 없으면 오류.
  • /test/b 폴더가 없으면 a폴더를 test폴더 아래에 b라는 이름으로 복사. => /test/b
  • /test/b 폴더가 있으면 a폴더를 b폴더 아래에 복사. => /test/b/a


[이동]


폴더 전체를 다른 폴더로 이동하기

  • 복사와 마찬가지로 상위폴더가 될 것인지 다른 이름이 될 것인지는 상황에 따라 다르다.

[명령어]
mv 원본폴더 목적지폴더
mv 원본폴더 목적지폴더/
mv 원본폴더/ 목적지폴더
mv 원본폴더/ 목적지폴더/
[예시]
mv -r a /test/b
mv -r a /test/b/
mv -r a/ /test/b
mv -r a/ /test/b/
  • /test 폴더가 없으면 오류.
  • /test/b 폴더가 없으면 a폴더를 test폴더 아래에 b라는 이름으로 이동. => /test/b
  • /test/b 폴더가 있으면 a폴더를 b폴더 아래로 이동. => /test/b/a


[삭제]


폴더 전체를 삭제하기


[명령어]

rm -rf 폴더
[예시]
rm -rf /test/b


'OS > LINUX' 카테고리의 다른 글

리눅스 라이브러리 생성(동적,정적)  (0) 2017.10.12
GDB 사용법  (0) 2017.06.30
리눅스 명령어  (0) 2016.10.13
find, grep 사용법  (0) 2016.08.12
특정 파일만 삭제  (0) 2016.07.07
반응형

copy

 http://blog.naver.com/top60331/220819788602

'OS > LINUX' 카테고리의 다른 글

GDB 사용법  (0) 2017.06.30
리눅스 폴더 복사 이동 삭제  (0) 2017.03.21
find, grep 사용법  (0) 2016.08.12
특정 파일만 삭제  (0) 2016.07.07
리눅스 ip 설정  (0) 2016.04.07
반응형

 

1. 폴더 또는 파일 찾기

   -> find 경로 -name 폴더명 또는 파일명

   -> 입력한 경로의 하위 경로까지 검색됨

 

2. 현재 디렉토리의 파일명 중에서 검색단어가 있는 코드 위치 찾기

   -> find . -name "파일명" -print -exec grep -n "검색단어" {} \;

 

3. 디렉토리의 파일명을 제외한 파일들을 삭제

   -> find 디렉토리 ! -name 파일명 -exec rm {} \;

 

4. 폴더 전체에서 파일 내부의 abc 라는 문자열 찾기

   -> grep -r abc /*

https://overcode.tistory.com/entry/%EB%A6%AC%EB%88%85%EC%8A%A4-%ED%8C%8C%EC%9D%BC-%EC%B0%BE%EA%B8%B0-%ED%8C%8C%EC%9D%BC%EC%86%8D-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%B0%BE%EA%B8%B0

 

리눅스 파일 찾기, 파일속 문자열 찾기

1. 리눅스 파일명으로 검색하는법. 사용법find [찾을위치] -name [파일명] 예) 최상위 폴더부터 하위로 'apache'로 시작하는 파일 찾기.find / -name 'apache*' 예) usr 폴더부터 하위로 'apa'로 시작하는 파일

overcode.tistory.com

https://zeuskwon-ds.tistory.com/135

 

[Linux] 파일 내 특정 문자열 찾기 - grep 기본

grep 명령어 - 파일 내 특정 문자열 찾기 리눅스에서 grep 명령어는 특정 파일에서 지정한 문자열이나 정규표현식을 포함한 행을 찾아서 출력해주는 명령어이다. 특히, tailo이나 ls 등 다양한 명령

zeuskwon-ds.tistory.com

 

 

참고)

http://solarixer.blogspot.kr/2007/09/find.html#!/2007/09/find.html

http://bahndal.egloos.com/524868

http://oiktoail.blog.me/220867152949

'OS > LINUX' 카테고리의 다른 글

리눅스 폴더 복사 이동 삭제  (0) 2017.03.21
리눅스 명령어  (0) 2016.10.13
특정 파일만 삭제  (0) 2016.07.07
리눅스 ip 설정  (0) 2016.04.07
make 컴파일 에러시 쉘 스크립트 중단  (0) 2016.03.23
반응형

알려주는 내용들은 거의 비슷함.

 

http://sv-story.blogspot.kr/2013/04/blog-post_28.html

http://h9911120.blog.me/50105195297

http://blog.naver.com/thdansgur/220609140473

https://www.linux.co.kr/home/lecture/index.php?cateNo=&secNo=&theNo=&leccode=201

'OS > LINUX' 카테고리의 다른 글

리눅스 명령어  (0) 2016.10.13
find, grep 사용법  (0) 2016.08.12
리눅스 ip 설정  (0) 2016.04.07
make 컴파일 에러시 쉘 스크립트 중단  (0) 2016.03.23
리눅스 쉘 색깔 바꾸기  (0) 2015.02.04
반응형

ifconfig eth0 192.168.1.123 netmask 255.255.255.0
route add default gw 192.168.1.1

'OS > LINUX' 카테고리의 다른 글

find, grep 사용법  (0) 2016.08.12
특정 파일만 삭제  (0) 2016.07.07
make 컴파일 에러시 쉘 스크립트 중단  (0) 2016.03.23
리눅스 쉘 색깔 바꾸기  (0) 2015.02.04
pthread_create, pthread_join, pthread_exit, pthread_self  (0) 2014.11.11
반응형

https://kldp.org/node/137438


makefile은 error가 나면 중지되겠지만,
make를 호출한 script는 make의 다음 문장을 계속 수행하겠지요.

bash의 경우 -e 옵션을 주면 error가 발생하면 종료하게 됩니다.
예를 들어 #!/bin/bash -e 를 script의 첫줄에 써주면 됩니다.

'OS > LINUX' 카테고리의 다른 글

특정 파일만 삭제  (0) 2016.07.07
리눅스 ip 설정  (0) 2016.04.07
리눅스 쉘 색깔 바꾸기  (0) 2015.02.04
pthread_create, pthread_join, pthread_exit, pthread_self  (0) 2014.11.11
리눅스 ip, gateway, netmask, mac 찾는 코드  (0) 2014.11.05
반응형

.bashrc에 아래와 같은 방법으로 원하는 내용을 추가한다.(ubuntu에서 했음)

LS_COLORS='d1=01;33'

 

출처:

http://blog.naver.com/kamakaru?Redirect=Log&logNo=50020998094

http://tuwlab.com/ece/10547

http://egloos.zum.com/sunyzero/v/4282610

반응형

pthread_attr: http://bitsoul.tistory.com/168

출처:

http://xucxo.blogspot.com/2011/03/linux-programming-thread.html: 함수에 대한 상세한 추가 설명이 좋다: 

http://underresearch.blogspot.kr/2013/05/pthread-thread.html

http://www.joinc.co.kr/w/Site/Thread/Beginning/PthreadApiReference#AEN226

http://www.morenice.kr/75

http://www.joinc.co.kr/w/Site/system_programing/Book_LSP/ch07_Thread

http://m.blog.naver.com/cky5122/80198083088

http://www.joinc.co.kr/w/Site/Thread/Beginning/PthreadApiReference#AEN226

https://kldp.org/node/93835

http://blog.naver.com/rbosc/90016327317

 

PThread - 리눅스에서 Thread 이용하기

Thread를 이용해야할 때까 있어서 공부를 했다
근데 리눅스에서 PThread를 사용하는 것이 윈도우 Visual Studio에서 지원하는 Thread를 사용하는 것보다 쉬워보였다.
그래서 PThread만 공부한 적이 있다.
처음엔 복잡한줄 알았는데 막상 공부해보니 쉬웠다.

처음 포스트인데 이번에는 PThread를 사용해서 간단한 프로그램을 작성할 것이다.
PThread는 리눅스에서만 되는것이 아니라 윈도우에서 MinGW를 설치하면 사용할 수 있다.

프로그램이 동작하는것은 이러하다.main에서 사용자에게 숫자 num을 입력받고 Thread 2개를 생성한다.하나의 Thread에서는 1부터 num까지 숫자를 카운트 하고 다른 하나의 Thread는 1부터 num까지 합한다.



또한 1부터 num까지 세는 Thread는 하나씩 셀 때마다 1000마이크로 초(1ms)를 쉰다
쉬지 않으면 SumThread가 끝나기 전에 CountThread가 끝나버려서 Thread가 제대로 돌아갔는지 알 수 없기 때문이다.

PThread를 사용하려면 pthread.h를 인클루드 시켜줘야 한다.
또한 pthread_t 라는 자료형의 변수와 함수들을 사용해 thread를 제어한다.

pthread_t라는 변수형은 thread의 id를 저장한다.

이 프로그램에서 사용한 함수들은 이렇다.

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

이 함수는 thread를 생성하는 함수이다.
첫번째 인자는 생성할 thread의 id
두번째 인자는 thread의 특성인데, 보통 NULL을 집어넣는다.
세번째 인자는 thread를 실행할 함수가 온다. thread를 실행할 함수는 포인터 함수이므로 인자값으로 올 수 있다.
네번째 인자는 thread를 실행할 함수에 넣어줄 인자값이 온다. 인자값은 하나지만 여러개의 인자값을 넣어주는 꼼수도 존재한다.(이건 다음에 포스팅)

int pthread_join(pthread_t thread, void **rval_ptr);

이 함수는 main이나 부모 thread에서 자식 thread가 종료할 때까지 대기하는 함수이다. main이나 부모thread가 끝나버리면 자식 thread 또한 종료되기 때문이다.
첫번째 인자는 생성한 thread의 id
두번째 인자는 해당 thread가 종료되면 return받을 변수. 리턴받을 값이 없으면 NULL을 넣으면 된다.
추가설명: https://www.joinc.co.kr/w/man/3/pthread_join

void pthread_exit(void *rval_ptr);


이 함수는 thread를 종료할 때 사용한다.
첫번째 인자는 thread를 종료하고 pthread_join() 함수 두번째 인자에 리턴할 변수. 리턴할 값이 없으면 NULL을 넣으면 된다.

pthread_t pthread_self(void)

이 함수는 실행하고 있는 thread의 id를 리턴한다.


또한 gcc에서 PThread를 사용할 소스를 컴파일 할때 맨 뒤에 -lpthread 명령어를 붙여줘야 한다.



이런식으로
MinGW로 컴파일 할때도 마찬가지.

아래는 소스.


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. void *CountThread(void *);
  5. void *SumThread(void *);
  6. int main(void)
  7. {
  8. int num;
  9. int result[2];
  10. int i, rc;
  11. pthread_t threads[2];
  12. printf("input number : ");
  13. scanf("%d", &num);
  14. pthread_create(&threads[0], NULL, &CountThread, (void *)&num); //Count를 할 Thread함수를 threads[0]에서 실행(인자값은 num)
  15. pthread_create(&threads[1], NULL, &SumThread, (void *)&num); //Sum을 구할 Thread함수를 threads[1]에서 실행(인자값은 num)
  16. for(i = 0; i < 2; i++)
  17. {
  18. rc = pthread_join(threads[i], (void **)&result[i]);
  19. if(rc != 0) //rc가 0이 아니면 오류 발생
  20. {
  21. printf("Error in thread[%d] : %d\n", i, rc);
  22. exit(1);
  23. }
  24. }
  25. printf("Result of CountThread : %d\n", result[0]);
  26. printf("Result of SumThread : %d\n", result[1]);
  27. return 0;
  28. }
  29. void *CountThread(void *arg)
  30. {
  31. int i;
  32. int num = *(int *)arg; //인자값을 사용해야할 때마다 일일이 void* 포인터에서 int* 포인터로 바꿔줘야 해서 귀찮아지므로 그냥 변수를 하나 만들어서 인자값을 넣어줌
  33. for(i = 1; i <= num; i++)
  34. {
  35. printf("In CountThread(0x%lx) : %d\n", pthread_self(), i);
  36. usleep(1000);
  37. }
  38. printf("CountThread End\n");
  39. pthread_exit(NULL); //인자값을 return하고 Thread함수 종료
  40. }
  41. void *SumThread(void *arg)
  42. {
  43. int result, i;
  44. int num = *(int *)arg;
  45. for(result = 0, i = 1; i <= num; i++)
  46. result += i;
  47. printf("SumThread End\n");
  48. pthread_exit((void *)result); //인자값을 return하고 Thread함수 종료(인자값이 void형 포인터로 들어가므로 void형 포인터로 형변환)
  49. }


앞에서 언급했듯이 pthread를 사용할 때 인자를 하나만 넣을 수 있는데 여러개를 넣는 꼼수가 존재한다. 구조체를 사용하는 방법이 있는데, 이것은 다음에 포스팅 하겠다.


반응형

인터넷에 돌아다니는 코드 막 붙여 넣었음. 코드 정리가 필요함;;;

 

출처: https://kldp.org/node/42683

        http://www.qnx.com/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Fi%2Fifaddrs.html

        http://pencil1031.tistory.com/69

        http://stackoverflow.com/questions/1779715/how-to-get-mac-address-of-your-machine-using-a-c-program

 

 

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#define dpt()        printf( "[dmsg] [file:%s, line:%d] \n", __FILE__, __LINE__ )


#include <stdlib.h>
#include <arpa/inet.h>


#include <sys/ioctl.h>


#define BUFSIZE 8192

struct route_info
{
  struct in_addr dstAddr;
  struct in_addr srcAddr;
  struct in_addr gateWay;
  char ifName[IF_NAMESIZE];
};


int readNlSock(int sockFd, char *bufPtr, size_t buf_size, int seqNum, int pId)
{
  struct nlmsghdr *nlHdr;
  int readLen = 0, msgLen = 0;

  do
  {
    /* Recieve response from the kernel */
    if((readLen = recv(sockFd, bufPtr, buf_size - msgLen, 0)) < 0)
    {
      perror("SOCK READ: ");
      return -1;
    }

    nlHdr = (struct nlmsghdr *)bufPtr;

    /* Check if the header is valid */
    if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR))
    {
      perror("Error in recieved packet");
      return -1;
    }

    /* Check if the its the last message */
    if(nlHdr->nlmsg_type == NLMSG_DONE)
    {
      break;
    }
    else
    {
      /* Else move the pointer to buffer appropriately */
      bufPtr += readLen;
      msgLen += readLen;
    }

    /* Check if its a multi part message */
    if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0)
    {
      /* return if its not */
      break;
    }
  }
  while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));

  return msgLen;
}

/* parse the route info returned */
int parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo)
{
  struct rtmsg *rtMsg;
  struct rtattr *rtAttr;
  int rtLen;

  rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);

  /* If the route is not for AF_INET or does not belong to main routing table then return. */
  if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
    return -1;

  /* get the rtattr field */
  rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
  rtLen = RTM_PAYLOAD(nlHdr);

  for(; RTA_OK(rtAttr,rtLen); rtAttr = RTA_NEXT(rtAttr,rtLen))
  {
    switch(rtAttr->rta_type)
    {
    case RTA_OIF:
      if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);
      break;

    case RTA_GATEWAY:
      memcpy(&rtInfo->gateWay, RTA_DATA(rtAttr), sizeof(rtInfo->gateWay));
      break;

    case RTA_PREFSRC:
      memcpy(&rtInfo->srcAddr, RTA_DATA(rtAttr), sizeof(rtInfo->srcAddr));
      break;

    case RTA_DST:
      memcpy(&rtInfo->dstAddr, RTA_DATA(rtAttr), sizeof(rtInfo->dstAddr));
      break;
    }
  }

  return 0;
}

// meat
int get_gatewayip(char *gatewayip, socklen_t size)
{
  int found_gatewayip = 0;

  struct nlmsghdr *nlMsg;
  struct rtmsg *rtMsg;
  struct route_info route_info;
  char msgBuf[BUFSIZE]; // pretty large buffer

  int sock, len, msgSeq = 0;

  /* Create Socket */
  if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
  {
    perror("Socket Creation: ");
    return(-1);
  }

  /* Initialize the buffer */
  memset(msgBuf, 0, sizeof(msgBuf));

  /* point the header and the msg structure pointers into the buffer */
  nlMsg = (struct nlmsghdr *)msgBuf;
  rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);

  /* Fill in the nlmsg header*/
  nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
  nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .

  nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.
  nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet.
  nlMsg->nlmsg_pid = getpid(); // PID of process sending the request.

  /* Send the request */
  if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0)
  {
    printf("Write To Socket Failed...\n");
    return -1;
  }

  /* Read the response */
  if((len = readNlSock(sock, msgBuf, sizeof(msgBuf), msgSeq, getpid())) < 0)
  {
    printf("Read From Socket Failed...\n");
    return -1;
  }

  /* Parse and print the response */
  for(; NLMSG_OK(nlMsg,len); nlMsg = NLMSG_NEXT(nlMsg,len))
  {
    memset(&route_info, 0, sizeof(route_info));
    if ( parseRoutes(nlMsg, &route_info) < 0 )
      continue;  // don't check route_info if it has not been set up

    // Check if default gateway
    if (strstr((char *)inet_ntoa(route_info.dstAddr), "0.0.0.0"))
    {
      // copy it over
      inet_ntop(AF_INET, &route_info.gateWay, gatewayip, size);
      found_gatewayip = 1;
      break;
    }
  }

  close(sock);

  return found_gatewayip;
}


static int
create_sock (const char *nic)
{
  struct sockaddr_nl addr;
  int                sock;

  memset (&addr, 0, sizeof (addr));
  addr.nl_family = AF_NETLINK;
  addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;

  sock = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  if (sock < 0)
    {
      printf ("failed to open NETLINK_ROUTE socket for %s - %s(%d)",
               nic, strerror (errno), errno);
      return -1;
    }

  if (bind (sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
      printf ( "failed to bind NETLINK_ROUTE socket for %s - %s(%d)",
                 nic, strerror (errno), errno);
      close (sock);
      return -1;
    }

  return sock;
}

static int
ip_changed (int         sock,
            const char *nic)
{
  struct nlmsghdr   *nlh;
  char               buffer[4096];
  int                len;
  int                idx;
  int                found;

  len = recv (sock, buffer, sizeof (buffer), 0);
  if (len <= 0)
    {
      printf ( "NETLINK_ROUTE socket recv() failedn");
      return -1;
    }

  found = 0;
  idx = if_nametoindex (nic);

  for (nlh = (struct nlmsghdr *)buffer;
       NLMSG_OK (nlh, len);
       nlh = NLMSG_NEXT (nlh, len))
    {
      if (nlh->nlmsg_type == NLMSG_DONE)
        break;
      if (nlh->nlmsg_type == NLMSG_ERROR)
        continue;
      if (!(NLMSG_OK (nlh, len)))
        continue;

      switch (nlh->nlmsg_type)
        {
        case RTM_NEWADDR:
          {
            struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA (nlh);

            if (ifa->ifa_index == idx)
              found = 1;
          }
          break;
        case RTM_NEWLINK:
          {
            struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA (nlh);

            if (ifi->ifi_index == idx)
              found = 1;
          }
          break;
        default:
          break;
        }
    }

  return found;
}

static int
get_nic_addr (const char     *nic,
              struct ifaddrs *ifaddr,
              int             wanted_family,
              char           *host,
              int             host_len,
              int            *active)
{
  struct ifaddrs *ifa;

  char test[100];


  for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
    {
      int family;
      int s;

      if (ifa->ifa_addr == NULL)
        continue;

      if (strcmp (ifa->ifa_name, nic))
        continue;

      /* Skip unwanted families. */
      family = ifa->ifa_addr->sa_family;
      if (family != wanted_family)
        continue;

      *active = (ifa->ifa_flags & IFF_RUNNING) ? 1 : 0;

      s = getnameinfo (ifa->ifa_addr,
                       family == AF_INET ? sizeof (struct sockaddr_in) :
                                           sizeof (struct sockaddr_in6),
                       host,
                       host_len,
                       NULL,
                       0,
                       NI_NUMERICHOST);
      if (s != 0)
        {
          printf ( "failed to getnameinfo() for '%s - %s(%d)",
                   ifa->ifa_name, strerror (errno), errno);
          continue;
        }


  memset(test, 0, 100);
      s = getnameinfo (ifa->ifa_netmask,
                       family == AF_INET ? sizeof (struct sockaddr_in) :
                                           sizeof (struct sockaddr_in6),
                       test,
                       100,
                       NULL,
                       0,
                       NI_NUMERICHOST);
  printf("netmask:%s\n",test);

  memset(test, 0, 100);
      s = getnameinfo (ifa->ifa_dstaddr,
                       family == AF_INET ? sizeof (struct sockaddr_in) :
                                           sizeof (struct sockaddr_in6),
                       test,
                       100,
                       NULL,
                       0,
                       NI_NUMERICHOST);
  printf("ifa_dstaddr:%s\n",test);

      /* Get the address of only the first network interface card. */
      return 1;
    }

  return 0;
}

static void
print_ip (const char *nic)
{
  struct ifaddrs *ifaddr;
  char            addr[NI_MAXHOST];
  int             active;

  if (getifaddrs (&ifaddr) == -1)
    {
      printf ( "failed to getifaddrs() - %s(%d)", strerror (errno), errno);
      return;
    }

  if (!get_nic_addr (nic, ifaddr, AF_INET, addr, sizeof (addr), &active))
    if (!get_nic_addr (nic, ifaddr, AF_INET6, addr, sizeof (addr), &active))
      {
        strcpy (addr, "127.0.0.1");
        active = 0;
      }

  freeifaddrs (ifaddr);

  printf ( "%s is %s (link %s)n", nic, addr, active ? "active" : "inactive");
}

 


int
main (void)
{
  char *nic = "eth0";
  int   sock;
 char gw[100];

    struct ifreq ifr;
    struct ifconf ifc;
    char buf[1024];
    int success = 0;

    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sock == -1) { /* handle error*/ };

    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) { /* handle error */ }

    struct ifreq* it = ifc.ifc_req;
    const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));

    for (; it != end; ++it) {
        strcpy(ifr.ifr_name, it->ifr_name);
        if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
            if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // don't count loopback
                if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
                    success = 1;
                    break;
                }
            }
        }
        else { /* handle error */ }
    }

    unsigned char mac_address[6];

    if (success) memcpy(mac_address, ifr.ifr_hwaddr.sa_data, 6);
 printf("mac_address:%02x\n",mac_address[0]);
 printf("mac_address:%02x\n",mac_address[1]);
 printf("mac_address:%02x\n",mac_address[2]);
 printf("mac_address:%02x\n",mac_address[3]);
 printf("mac_address:%02x\n",mac_address[4]);
 printf("mac_address:%02x\n",mac_address[5]);
 


 
  print_ip (nic);

dpt();
  sock = create_sock (nic);
  if (sock < 0)
    return -1;

  memset(gw, 0, 100);

 get_gatewayip(gw,100);
 printf("gw:%s\n",gw);

dpt();
  while (1)
    {
      int ret;

      ret = ip_changed (sock, nic);
      if (ret < 0)
        return -1;

      if (ret)
        print_ip (nic);
    }

  close (sock);

  return 0;
}

 

 

+ Recent posts