tag:blogger.com,1999:blog-17709746939439428962024-02-07T21:32:44.598-08:00Sauron@Mordorlinux, c++, great food...samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.comBlogger26125tag:blogger.com,1999:blog-1770974693943942896.post-29115295045088591222014-12-10T01:34:00.000-08:002014-12-10T06:05:20.477-08:00Setting up shared memory with robust pthread_mutex and pthread_cond <br />
I've tried to experiment with shared memory.<br />
Eventually, I figured out that you can use pthread_mutex and pthread_contion to synchronize the access of a shared memory.<br />
<br />
During the process, I found out that it is very important to make the pthread_mutex "robust".<br />
<br />
This so called robust mutex is important because this mutex can be shared by multiple processes, and therefore if one process crashes without releasing the mutex, all the other process could be stuck forever.<br />
<br />
A robust mutex will release it's possession to the next process, if the current mutex possessing process crashes.<br />
The pthread_mutex_lock() of the new mutex possessing process, will return with "EOWNERDEAD".<br />
<br />
On this event, the new process should be aware that the share memory might have experienced a exception; therefore, it should be checked.<br />
<br />
Once the shared memory and mutex is recovered, you should use "pthread_mutex_consistent()" to return the mutex to a "consistent" state.<br />
<br />
<br />
<br />
the soure code needs to be built with "-lrt" and "-lpthread".<br />
<br />
source code: <br />
<br />
<!-- HTML generated using hilite.me -->
<br />
<div style="background: #ffffff; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #557799;">#include <fcntl.h></span>
<span style="color: #557799;">#include <sys/stat.h></span>
<span style="color: #557799;">#include <errno.h></span>
<span style="color: #557799;">#include <sys/mman.h></span>
<span style="color: #557799;">#include <sys/types.h> </span><span style="color: #888888;">//shm_open</span>
<span style="color: #557799;">#include <stdio.h> </span><span style="color: #888888;">//printf</span>
<span style="color: #557799;">#include <stdlib.h> </span><span style="color: #888888;">//exit</span>
<span style="color: #557799;">#include <unistd.h> </span><span style="color: #888888;">//close</span>
<span style="color: #557799;">#include <string.h> </span><span style="color: #888888;">//strerror</span>
<span style="color: #557799;">#include <pthread.h></span><span style="color: #888888;">//pthread_cond* pthread_mutex*</span>
<span style="color: #888888;">/* This will be created under /dev/shm/ */</span>
<span style="color: #557799;">#define STATE_FILE "/program.shared" </span>
<span style="color: #888888;">/* Define a struct we wish to share. Notice that we will allocate </span>
<span style="color: #888888;"> * * only sizeof SHARED_VAR, so all sizes are constant </span>
<span style="color: #888888;"> * */</span>
<span style="color: #008800; font-weight: bold;">typedef</span> <span style="color: #008800; font-weight: bold;">struct</span>
{
<span style="color: #333399; font-weight: bold;">int</span> flags;
<span style="color: #333399; font-weight: bold;">pthread_mutex_t</span> mutex;
<span style="color: #333399; font-weight: bold;">pthread_cond_t</span> cond;
} SHARED_VAR;
<span style="color: #333399; font-weight: bold;">int</span> <span style="color: #0066bb; font-weight: bold;">shared_mutex_init</span>(SHARED_VAR <span style="color: #333333;">*</span>conf)
{
<span style="color: #333399; font-weight: bold;">pthread_mutexattr_t</span> mutexAttr;
pthread_mutexattr_init(<span style="color: #333333;">&</span>mutexAttr);
<span style="color: #008800; font-weight: bold;">do</span>{
<span style="color: #008800; font-weight: bold;">if</span>(pthread_mutexattr_setpshared(<span style="color: #333333;">&</span>mutexAttr, PTHREAD_PROCESS_SHARED) <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">0</span> ){
printf(<span style="background-color: #fff0f0;">"failed to set PTHREAD_PROCESS_SHARED</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
<span style="color: #008800; font-weight: bold;">break</span>;
}
<span style="color: #008800; font-weight: bold;">if</span>(pthread_mutexattr_setrobust(<span style="color: #333333;">&</span>mutexAttr, PTHREAD_MUTEX_ROBUST) <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">0</span>){
printf(<span style="background-color: #fff0f0;">"failed to set PTHREAD_MUTEX_ROBUST</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
<span style="color: #008800; font-weight: bold;">break</span>;
}
<span style="color: #008800; font-weight: bold;">if</span>(pthread_mutex_init(<span style="color: #333333;">&</span>(conf<span style="color: #333333;">-></span>mutex), <span style="color: #333333;">&</span>mutexAttr) <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">0</span>){
printf(<span style="background-color: #fff0f0;">"failed to init mutex</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
<span style="color: #008800; font-weight: bold;">break</span>;
}
printf(<span style="background-color: #fff0f0;">"%s success</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>, __FUNCTION__);
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
}<span style="color: #008800; font-weight: bold;">while</span>(<span style="color: #0000dd; font-weight: bold;">0</span>);
pthread_mutexattr_destroy(<span style="color: #333333;">&</span>mutexAttr);
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span>;
}
<span style="color: #333399; font-weight: bold;">int</span> <span style="color: #0066bb; font-weight: bold;">shared_cond_init</span>(SHARED_VAR <span style="color: #333333;">*</span>conf)
{
<span style="color: #333399; font-weight: bold;">pthread_condattr_t</span> condAttr;
pthread_condattr_init(<span style="color: #333333;">&</span>condAttr);
<span style="color: #008800; font-weight: bold;">do</span>{
<span style="color: #008800; font-weight: bold;">if</span>(pthread_condattr_setpshared(<span style="color: #333333;">&</span>condAttr, PTHREAD_PROCESS_SHARED) <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">0</span> ){
printf(<span style="background-color: #fff0f0;">"failed to set PTHREAD_PROCESS_SHARED</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
<span style="color: #008800; font-weight: bold;">break</span>;
}
<span style="color: #008800; font-weight: bold;">if</span>(pthread_cond_init(<span style="color: #333333;">&</span>(conf<span style="color: #333333;">-></span>cond), <span style="color: #333333;">&</span>condAttr) <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">0</span>){
printf(<span style="background-color: #fff0f0;">"failed to init mutex</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
<span style="color: #008800; font-weight: bold;">break</span>;
}
printf(<span style="background-color: #fff0f0;">"%s success</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>, __FUNCTION__);
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
}<span style="color: #008800; font-weight: bold;">while</span>(<span style="color: #0000dd; font-weight: bold;">0</span>);
pthread_condattr_destroy(<span style="color: #333333;">&</span>condAttr);
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span>;
}
<span style="color: #333399; font-weight: bold;">int</span> <span style="color: #0066bb; font-weight: bold;">main</span> (<span style="color: #333399; font-weight: bold;">void</span>)
{
<span style="color: #333399; font-weight: bold;">int</span> first <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
<span style="color: #333399; font-weight: bold;">int</span> i;
<span style="color: #333399; font-weight: bold;">int</span> shm_fd;
<span style="color: #008800; font-weight: bold;">static</span> SHARED_VAR <span style="color: #333333;">*</span>conf;
<span style="color: #333399; font-weight: bold;">int</span> process_id;
<span style="color: #008800; font-weight: bold;">struct</span> timespec abstime;
<span style="color: #888888;">/* Try to open the shm instance with O_EXCL,</span>
<span style="color: #888888;"> * * this tests if the shm is already opened by someone else </span>
<span style="color: #888888;"> * */</span>
<span style="color: #008800; font-weight: bold;">if</span>((shm_fd <span style="color: #333333;">=</span> shm_open(STATE_FILE, (O_CREAT <span style="color: #333333;">|</span> O_EXCL <span style="color: #333333;">|</span> O_RDWR),
(S_IREAD <span style="color: #333333;">|</span> S_IWRITE))) <span style="color: #333333;">></span> <span style="color: #0000dd; font-weight: bold;">0</span> ) {
first <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">1</span>; <span style="color: #888888;">/* We are the first instance */</span>
}
<span style="color: #008800; font-weight: bold;">else</span> <span style="color: #008800; font-weight: bold;">if</span>((shm_fd <span style="color: #333333;">=</span> shm_open(STATE_FILE, (O_CREAT <span style="color: #333333;">|</span> O_RDWR),
(S_IREAD <span style="color: #333333;">|</span> S_IWRITE))) <span style="color: #333333;"><</span> <span style="color: #0000dd; font-weight: bold;">0</span>) {
<span style="color: #888888;">/* Try to open the shm instance normally and share it with </span>
<span style="color: #888888;"> * * existing clients </span>
<span style="color: #888888;"> * */</span>
printf(<span style="background-color: #fff0f0;">"Could not create shm object. %s</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>, strerror(errno));
<span style="color: #008800; font-weight: bold;">return</span> errno;
}
<span style="color: #888888;">/* Set the size of the SHM to be the size of the struct. */</span>
ftruncate(shm_fd, <span style="color: #008800; font-weight: bold;">sizeof</span>(SHARED_VAR));
<span style="color: #888888;">/* Connect the conf pointer to set to the shared memory area,</span>
<span style="color: #888888;"> * * with desired permissions </span>
<span style="color: #888888;"> * */</span>
<span style="color: #008800; font-weight: bold;">if</span>((conf <span style="color: #333333;">=</span> mmap(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #008800; font-weight: bold;">sizeof</span>(SHARED_VAR), (PROT_READ <span style="color: #333333;">|</span> PROT_WRITE),
MAP_SHARED, shm_fd, <span style="color: #0000dd; font-weight: bold;">0</span>)) <span style="color: #333333;">==</span> MAP_FAILED) {
<span style="color: #008800; font-weight: bold;">return</span> errno;
}
<span style="color: #008800; font-weight: bold;">if</span>(first) {
<span style="color: #888888;">/* Run a set up for the first time, fill some args */</span>
printf(<span style="background-color: #fff0f0;">"First creation of the shm. Setting up default values</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
conf<span style="color: #333333;">-></span>flags <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
}
<span style="color: #008800; font-weight: bold;">else</span>
{
printf(<span style="background-color: #fff0f0;">"Value of flags = %d</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>, conf<span style="color: #333333;">-></span>flags);
}
<span style="color: #008800; font-weight: bold;">if</span>(shared_mutex_init(conf) <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">0</span>){
printf(<span style="background-color: #fff0f0;">"failed to create shared_mutex</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
}
<span style="color: #008800; font-weight: bold;">if</span>(shared_cond_init(conf) <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">0</span>){
printf(<span style="background-color: #fff0f0;">"failed to create shared_cond</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
}
<span style="color: #333399; font-weight: bold;">int</span> lockReturn;
<span style="color: #333399; font-weight: bold;">int</span> consistent;
<span style="color: #333399; font-weight: bold;">int</span> condReturn;
<span style="color: #008800; font-weight: bold;">do</span>{
lockReturn <span style="color: #333333;">=</span> pthread_mutex_lock(<span style="color: #333333;">&</span>(conf<span style="color: #333333;">-></span>mutex));
<span style="color: #008800; font-weight: bold;">if</span>(lockReturn <span style="color: #333333;">==</span> EOWNERDEAD){
<span style="color: #888888;">/*Previous process died before releasing the mutex do some cleanup */</span>
consistent <span style="color: #333333;">=</span> pthread_mutex_consistent(<span style="color: #333333;">&</span>(conf<span style="color: #333333;">-></span>mutex));<span style="color: #888888;">/*address that the cleanup is done*/</span>
}<span style="color: #008800; font-weight: bold;">else</span> <span style="color: #008800; font-weight: bold;">if</span>(lockReturn <span style="color: #333333;">!</span> <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>){
<span style="color: #888888;">/*didn't get lock*/</span>
<span style="color: #008800; font-weight: bold;">continue</span>;
}
<span style="color: #008800; font-weight: bold;">if</span>(<span style="color: #888888;">/*need to wait*/</span>){
clock_gettime(CLOCK_REALTIME, <span style="color: #333333;">&</span>abstime);
abstime.tv_sec <span style="color: #333333;">+=</span> <span style="color: #0000dd; font-weight: bold;">5</span>;
condReturn <span style="color: #333333;">=</span> pthread_cond_timedwait(<span style="color: #333333;">&</span>(conf<span style="color: #333333;">-></span>cond), <span style="color: #333333;">&</span>(conf<span style="color: #333333;">-></span>mutex), <span style="color: #333333;">&</span>abstime);
}
<span style="color: #008800; font-weight: bold;">if</span>(<span style="color: #888888;">/*need to signal*/</span>){
pthread_cond_signal(<span style="color: #333333;">&</span>(conf<span style="color: #333333;">-></span>cond));
}
<span style="color: #888888;">/*do something*/</span>
pthread_mutex_unlock(<span style="color: #333333;">&</span>(conf<span style="color: #333333;">-></span>mutex));
}<span style="color: #008800; font-weight: bold;">while</span>( <span style="color: #888888;">/*running()*/</span>);
close(shm_fd);
exit(<span style="color: #0000dd; font-weight: bold;">0</span>);
}
</pre>
</td></tr>
</tbody></table>
</div>
samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-44936889621369047492014-12-09T19:15:00.000-08:002014-12-10T06:16:14.230-08:00How you receive an ethernet packet: from the ethernet driver to the BSD socket.<br />
I've worked with lots of Ethernet driver developers and network applicaton engineers in the past few years.<br />
It surprises me how one person might have dedicated years of programming into writing Ethernet MAC drivers and BSD sockets, but never bothered to know how the data is passed from the hw driver through the IP stack to the BSD socket API.<br />
<br />
I wanted to share this because I think some times it is better to know the whole picture.<br />
<br />
p.s.<br />
I've referenced the kernel source code, which I was currently working on; therefore, the function & variable names might differ in various kernels, however the idea is the same.<br />
<br />
OVERVIEW:<br />
<br />
[HW driver] --> lookup packet type(ipv4? ipv6? ...etc) --> lookup destination (do route, drop, or input ...) [if(input)]--> lookup protocol(tcp, udp, icmp ... etc) -->lookup socket --> copy to user_space<br />
<br />
PATH:<br />
<br />
net device driver calls "netif_receive_sk()"<br />
<br />
netif_receive_sk(){<br />
<br />
//1. check and return struct packet_type *<br />
//2. exec packet_type->function<br />
//<br />
// example:<br />
// returned : struct packet_type ipv6_packet_type{<br />
// .func = ipv6_rcv(struct sk_buff)<br />
// }<br />
//<br />
// struct sk_buff{<br />
// struct dst_entry ._skb_dst = ipv6_input()<br />
// }<br />
<br />
packet_type->func(); <br />
}<br />
<br />
<br />
ipv6_rcv()<br />
{<br />
//1. look up the destination(returns a "struct dst_entry *")<br />
//2. calls ip6_rcv_finish()<br />
NF_INET_PRE_ROUTING(ip6_rcv_finish())<br />
}<br />
<br />
ip6_rcv_finish(){<br />
// 1. exec dst_entry->input() by calling ip6_route_input()<br />
//<br />
//example:<br />
//dstinsation is a ipv6 destinaition<br />
//<br />
//struct dst_entry<br />
//{<br />
// .intput = ip6_input<br />
//}<br />
//<br />
ip6_route_input() //ip6_route_input() looks up all possible routes if(input){est_entry->input()}<br />
<br />
}<br />
<br />
<br />
<br />
ip6_input()<br />
{<br />
//calls ip6_input_finish()<br />
NF_HOOK(ip6_input_finish());<br />
}<br />
<br />
ip6_input_finish()<br />
{<br />
//1. lookup protocol by checking with the ip header(TCP or ICMP or UDP...etc)<br />
//2. returns a "struct inet_protocol"<br />
//3. exec inet_protocol.handler() <br />
//<br />
//example:<br />
//returns struct inet6_protocol tcpv6_protocol{<br />
// .handler = tcp_v6_rcv()<br />
// }<br />
//<br />
<br />
protocol.handler() // according to example, calls tcp_v6_rcv() <br />
}<br />
<br />
tcp_v6_rcv()<br />
{<br />
__inet6_lookup_skb() // lookup, match or create socket<br />
tcp_v6_do_rcv();<br />
}<br />
<br />
tcp_v6_do_rcv()<br />
{<br />
tcp_rcv_established() -->skb_copy_datagram_iovec()-->memcpy_toiovec()-->copy_to_user()<br />
}<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
others:<br />
<br />
addrconf_dst_alloc() //create dst_entrysamuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-29299193933165919132012-09-17T00:21:00.002-07:002014-12-10T06:17:29.476-08:00Interesting things with openSSL programing. It's not hard to find a OpenSSL programming tutorial or some example code on the internet, but there are some interesting detail that is not mentioned in most of the articles online.<br />
A while ago, I was involved in a new project that gave me the chance to play with libSSL for a while, I did read some tutorials and studied some examples on the Internet; but when I was testing the actual source code, I found out that It was quite unstable; the software that I wrote acts unexpectedly as if It has its own mind and wound crash due to segmentation faults or memory violations unpredictably.<br />
After tracing the actual source code of the OpenSSL library, I figured out a few interesting things that I would like to share.<br />
<ol>
<li> OpenSSL library could be build without multi-thread support; since most commercial software products are designed with multi-thread, please be sure to check if the library that you're using is build with multi-thread enabled.</li>
<li>Even if you have enabled the multi-thread support, OpenSSL library is not thread safe right outside of the box, you have to implement two operations:</li>
<ol>
<li>first is a function that will return the current thread ID.</li>
<li>the second is a function that will handle the mutex lock and unlock actuion.</li>
</ol>
<li>the two operation functions mentioned in the previous section should be introduced to the OpenSSL library by using some provided APIs like:</li>
<ul>
<li>CRYPTO_set_id_callback</li>
<li>CRYPTO_set_locking_callback</li>
</ul>
</ol>
if you are looking for a example code you can download the openssl <a href="http://www.openssl.org/source/" rel="nofollow" target="_blank">source code</a> and checkout the demo code (crypto/threads/mttest.c), which comes with the source.<br />
<br />
<br />
<br />
<ol>
</ol>
samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-84725144378036104902012-09-12T19:26:00.001-07:002012-09-12T19:37:18.819-07:00Speeding up TCP connection lost detection in a TCP client applicationWhen we're writing a TCP server, it is very easy to detect connection lost of a remote TCP peer by enabling "TCP keep alive";with this feature enabled, when no data is actually transmitting on the present TCP connection, a "tcp-keep-alive" is sent and a "ack" return from the remote peer is required.<br />
If there is no "ack" after several retries, the connection is determined as "lost" by the OS.<br />
When connection lost is detected, the system(Linux) will signal you by returning "read data ready" on the "select()" function, but returning a zero length data on "read()".<br />
But, when we're writing a TCP client, the tricky part is: as a client, 90% of the time we always have data to send, so when the connection is lost, the TCP stack automatically retransmits the data; as a result, before "tcp-retransmit" actually timeouts, the "tcp-kee-alive" mechanism will not kick in.<br />
Thus, if you are looking for a way to speed up "TCP connection lost" detection efficiency in a client application, this "keep alive" mechanism will do you no good.<br />
A possible approach is to use "ioctl(socket , SIOCOUTQ, &BufferUsedSize)" to return the actual data size that is still waiting in the send queue, if no data has been successfully sent for a certain period of time, than the connection is possibly lost.<br />
<br />
reference:<br />
man 7 tcp<br />
<br />samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-91420011840477496442011-07-17T18:43:00.000-07:002011-07-17T18:49:30.055-07:00getting both IPv4 and IPv6 addresses of all local network interfaces via "getifaddrs"In the old days, we often use ioctl to get the IPv4 address of our local interfaces via <code>:</code><br />
<code>ioctl(socketfd, SIOCGIFCONF, (struct ifconf)&buffer);</code><br />
if we are interested in the IPv6 local addresses, we can always check them out via "/proc", for example, this is what we might do:<br />
<br />
[sauron@icomserver ~]$ cat /proc/net/if_inet6<br />
<span style="color: blue;">fe8000000000000002d0c9fffebb030b </span><span style="color: #b45f06;">03</span> <span style="color: purple;">40</span> <span style="color: #38761d;">20</span> <span style="color: #3d85c6;">80</span> <span style="color: red;"> eth1</span><br />
<span style="color: blue;">00000000000000000000000000000001</span> <span style="color: #b45f06;">01</span> <span style="color: purple;">80</span> <span style="color: #38761d;">10</span> <span style="color: #3d85c6;">80</span> <span style="color: red;">lo</span><br />
<ol type="1"><li style="color: blue;">IPv6 address displayed in 32 hexadecimal chars without colons as separator</li>
<li style="color: #b45f06;">Netlink device number (interface index) in hexadecimal (see “ip addr” , too)</li>
<li style="color: purple;">Prefix length in hexadecimal</li>
<li style="color: #38761d;">Scope value (see kernel source “ include/net/ipv6.h” and “net/ipv6/addrconf.c” for more)</li>
<li style="color: #3d85c6;">Interface flags (see “include/linux/rtnetlink.h” and “net/ipv6/addrconf.c” for more)</li>
<li style="color: red;">Device name </li>
</ol>Quite easy, right? But what should we do to get both IPv4 and IPv6 addresses via the same API?<br />
if you are seeking for a IPv4 and IPv6 total solution, then "getifaddrs" is the answer that satisfies all your needs. <br />
<br />
reference:<br />
man 3 getifaddrs, man 3 getaddrinfo, man 3 getnameinfo<br />
<br />
<div><pre class="alt2" dir="ltr" style="border: 1px inset; height: 400px; margin: 0px; overflow: auto; padding: 6px; text-align: left; width: 650px;"><style type="text/css">
.comment { color: #999999; font-style: italic; }
.pre { color: #000099; }
.string { color: #009900; }
.char { color: #009900; }
.float { color: #996600; }
.int { color: #999900; }
.bool { color: #000000; font-weight: bold; }
.type { color: #FF6633; }
.flow { color: #FF0000; }
.keyword { color: #990000; }
.operator { color: #663300; font-weight: bold; }
.operator { color: #663300; font-weight: bold; }
</style>
<pre><span class="pre">#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
</span><span class="type">
int</span><span class="keyword">
main</span><span class="operator">(</span><span class="type">int</span> argc<span class="operator">,</span><span class="type"> char</span><span class="operator"> *</span>argv<span class="operator">[])
{</span><span class="keyword">
struct</span> ifaddrs<span class="operator"> *</span>ifaddr<span class="operator">, *</span>ifa<span class="operator">;</span><span class="type">
int</span> family<span class="operator">,</span> s<span class="operator">;</span><span class="type">
char</span> host<span class="operator">[</span>NI_MAXHOST<span class="operator">];</span><span class="flow">
if</span><span class="operator"> (</span>getifaddrs<span class="operator">(&</span>ifaddr<span class="operator">) == -</span><span class="int">1</span><span class="operator">) {</span>
perror<span class="operator">(</span><span class="string">"getifaddrs"</span><span class="operator">);</span>
exit<span class="operator">(</span>EXIT_FAILURE<span class="operator">);
}</span><span class="comment">
/* Walk through linked list, maintaining head pointer so we
* can free list later */</span><span class="flow">
for</span><span class="operator"> (</span>ifa<span class="operator"> =</span> ifaddr<span class="operator">;</span> ifa<span class="operator"> !=</span> NULL<span class="operator">;</span> ifa<span class="operator"> =</span> ifa<span class="operator">-></span>ifa_next<span class="operator">) {</span>
family<span class="operator"> =</span> ifa<span class="operator">-></span>ifa_addr<span class="operator">-></span>sa_family<span class="operator">;</span><span class="comment">
/* Display interface name and family (including symbolic
* form of the latter for the common families) */</span>
printf<span class="operator">(</span><span class="string">"%s address family: %d%s\n"</span><span class="operator">,</span>
ifa<span class="operator">-></span>ifa_name<span class="operator">,</span> family<span class="operator">,
(</span>family<span class="operator"> ==</span> AF_PACKET<span class="operator">) ?</span><span class="string"> " (AF_PACKET)"</span><span class="operator"> :
(</span>family<span class="operator"> ==</span> AF_INET<span class="operator">) ?</span><span class="string"> " (AF_INET)"</span><span class="operator"> :
(</span>family<span class="operator"> ==</span> AF_INET6<span class="operator">) ?</span><span class="string"> " (AF_INET6)"</span><span class="operator"> :</span><span class="string"> ""</span><span class="operator">);</span><span class="comment">
/* For an AF_INET* interface address, display the address */</span><span class="flow">
if</span><span class="operator"> (</span>family<span class="operator"> ==</span> AF_INET<span class="operator"> ||</span> family<span class="operator"> ==</span> AF_INET6<span class="operator">) {</span>
s<span class="operator"> =</span> getnameinfo<span class="operator">(</span>ifa<span class="operator">-></span>ifa_addr<span class="operator">,
(</span>family<span class="operator"> ==</span> AF_INET<span class="operator">) ?</span><span class="keyword"> sizeof</span><span class="operator">(</span><span class="keyword">struct</span> sockaddr_in<span class="operator">) :</span><span class="keyword">
sizeof</span><span class="operator">(</span><span class="keyword">struct</span> sockaddr_in6<span class="operator">),</span>
host<span class="operator">,</span> NI_MAXHOST<span class="operator">,</span> NULL<span class="operator">,</span><span class="int"> 0</span><span class="operator">,</span> NI_NUMERICHOST<span class="operator">);</span><span class="flow">
if</span><span class="operator"> (</span>s<span class="operator"> !=</span><span class="int"> 0</span><span class="operator">) {</span>
printf<span class="operator">(</span><span class="string">"getnameinfo() failed: %s\n"</span><span class="operator">,</span> gai_strerror<span class="operator">(</span>s<span class="operator">));</span>
exit<span class="operator">(</span>EXIT_FAILURE<span class="operator">);
}</span>
printf<span class="operator">(</span><span class="string">"\taddress: <%s>\n"</span><span class="operator">,</span> host<span class="operator">);
}
}</span>
freeifaddrs<span class="operator">(</span>ifaddr<span class="operator">);</span>
exit<span class="operator">(</span>EXIT_SUCCESS<span class="operator">);
}</span></pre></pre></div>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-57393539473433177242011-07-06T19:16:00.000-07:002012-09-18T10:46:04.139-07:00how to get default gateway via rtnetlink (c code example)<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
this is a example code showing you how to get the ip of the default gateway via netlink socket. I've also attached some useful information if you want to study netlink</div>
<div class="smallfont" style="margin-bottom: 2px;">
</div>
<div class="smallfont" style="margin-bottom: 2px;">
</div>
further reading:<br />
<h3 class="post-title entry-title" style="font-weight: normal;">
<a href="http://linux-hacks.blogspot.com/2009/01/sample-code-to-learn-netlink.html" target="_blank">Sample Code To Learn Netlink Infrastructure</a></h3>
<a href="http://smacked.org/docs/netlink.pdf" target="_blank"> understanding and programming with netlink sockets(PDF)</a><br />
<br />
reference:<br />
man 3 rtnetlink, man 7 rtnetlink, man 3 netlink, man 7 netlink<br />
<br />
<br />
example code:<br />
<div>
<pre class="alt2" dir="ltr" style="border: 1px inset; height: 400px; margin: 0px; overflow: auto; padding: 6px; text-align: left; width: 650px;"><pre><span class="pre">#include <asm/types.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/types.h>
#define BUFSIZE 8192
</span><span class="type">
char</span> gateway<span class="operator">[</span><span class="int">255</span><span class="operator">];</span><span class="keyword">
struct</span> route_info<span class="operator">{</span>
u_int dstAddr<span class="operator">;</span>
u_int srcAddr<span class="operator">;</span>
u_int gateWay<span class="operator">;</span><span class="type">
char</span> ifName<span class="operator">[</span>IF_NAMESIZE<span class="operator">];
};</span><span class="type">
int</span> readNlSock<span class="operator">(</span><span class="type">int</span> sockFd<span class="operator">,</span><span class="type"> char</span><span class="operator"> *</span>bufPtr<span class="operator">,</span><span class="type"> int</span> seqNum<span class="operator">,</span><span class="type"> int</span> pId<span class="operator">){</span><span class="keyword">
struct</span> nlmsghdr<span class="operator"> *</span>nlHdr<span class="operator">;</span><span class="type">
int</span> readLen<span class="operator"> =</span><span class="int"> 0</span><span class="operator">,</span> msgLen<span class="operator"> =</span><span class="int"> 0</span><span class="operator">;</span><span class="flow">
do</span><span class="operator">{</span><span class="comment">
/* Recieve response from the kernel */</span><span class="flow">
if</span><span class="operator">((</span>readLen<span class="operator"> =</span> recv<span class="operator">(</span>sockFd<span class="operator">,</span> bufPtr<span class="operator">,</span> BUFSIZE<span class="operator"> -</span> msgLen<span class="operator">,</span><span class="int"> 0</span><span class="operator">)) <</span><span class="int"> 0</span><span class="operator">){</span>
perror<span class="operator">(</span><span class="string">"SOCK READ: "</span><span class="operator">);</span><span class="flow">
return</span><span class="operator"> -</span><span class="int">1</span><span class="operator">;
}</span>
nlHdr<span class="operator"> = (</span><span class="keyword">struct</span> nlmsghdr<span class="operator"> *)</span>bufPtr<span class="operator">;</span><span class="comment">
/* Check if the header is valid */</span><span class="flow">
if</span><span class="operator">((</span>NLMSG_OK<span class="operator">(</span>nlHdr<span class="operator">,</span> readLen<span class="operator">) ==</span><span class="int"> 0</span><span class="operator">) || (</span>nlHdr<span class="operator">-></span>nlmsg_type<span class="operator"> ==</span> NLMSG_ERROR<span class="operator">))
{</span>
perror<span class="operator">(</span><span class="string">"Error in recieved packet"</span><span class="operator">);</span><span class="flow">
return</span><span class="operator"> -</span><span class="int">1</span><span class="operator">;
}</span><span class="comment">
/* Check if the its the last message */</span><span class="flow">
if</span><span class="operator">(</span>nlHdr<span class="operator">-></span>nlmsg_type<span class="operator"> ==</span> NLMSG_DONE<span class="operator">) {</span><span class="flow">
break</span><span class="operator">;
}</span><span class="flow">
else</span><span class="operator">{</span><span class="comment">
/* Else move the pointer to buffer appropriately */</span>
bufPtr<span class="operator"> +=</span> readLen<span class="operator">;</span>
msgLen<span class="operator"> +=</span> readLen<span class="operator">;
}</span><span class="comment">
/* Check if its a multi part message */</span><span class="flow">
if</span><span class="operator">((</span>nlHdr<span class="operator">-></span>nlmsg_flags<span class="operator"> &</span> NLM_F_MULTI<span class="operator">) ==</span><span class="int"> 0</span><span class="operator">) {</span><span class="comment">
/* return if its not */</span><span class="flow">
break</span><span class="operator">;
}
}</span><span class="flow"> while</span><span class="operator">((</span>nlHdr<span class="operator">-></span>nlmsg_seq<span class="operator"> !=</span> seqNum<span class="operator">) || (</span>nlHdr<span class="operator">-></span>nlmsg_pid<span class="operator"> !=</span> pId<span class="operator">));</span><span class="flow">
return</span> msgLen<span class="operator">;
}</span><span class="comment">
/* For printing the routes. */</span><span class="type">
void</span> printRoute<span class="operator">(</span><span class="keyword">struct</span> route_info<span class="operator"> *</span>rtInfo<span class="operator">)
{</span><span class="type">
char</span> tempBuf<span class="operator">[</span><span class="int">512</span><span class="operator">];</span><span class="comment">
/* Print Destination address */</span><span class="flow">
if</span><span class="operator">(</span>rtInfo<span class="operator">-></span>dstAddr<span class="operator"> !=</span><span class="int"> 0</span><span class="operator">)</span>
strcpy<span class="operator">(</span>tempBuf<span class="operator">, (</span><span class="type">char</span><span class="operator"> *)</span>inet_ntoa<span class="operator">(</span>rtInfo<span class="operator">-></span>dstAddr<span class="operator">));</span><span class="flow">
else</span>
sprintf<span class="operator">(</span>tempBuf<span class="operator">,</span><span class="string">"*.*.*.*\t"</span><span class="operator">);</span>
fprintf<span class="operator">(</span>stdout<span class="operator">,</span><span class="string">"%s\t"</span><span class="operator">,</span> tempBuf<span class="operator">);</span><span class="comment">
/* Print Gateway address */</span><span class="flow">
if</span><span class="operator">(</span>rtInfo<span class="operator">-></span>gateWay<span class="operator"> !=</span><span class="int"> 0</span><span class="operator">)</span>
strcpy<span class="operator">(</span>tempBuf<span class="operator">, (</span><span class="type">char</span><span class="operator"> *)</span>inet_ntoa<span class="operator">(</span>rtInfo<span class="operator">-></span>gateWay<span class="operator">));</span><span class="flow">
else</span>
sprintf<span class="operator">(</span>tempBuf<span class="operator">,</span><span class="string">"*.*.*.*\t"</span><span class="operator">);</span>
fprintf<span class="operator">(</span>stdout<span class="operator">,</span><span class="string">"%s\t"</span><span class="operator">,</span> tempBuf<span class="operator">);</span><span class="comment">
/* Print Interface Name*/</span>
fprintf<span class="operator">(</span>stdout<span class="operator">,</span><span class="string">"%s\t"</span><span class="operator">,</span> rtInfo<span class="operator">-></span>ifName<span class="operator">);</span><span class="comment">
/* Print Source address */</span><span class="flow">
if</span><span class="operator">(</span>rtInfo<span class="operator">-></span>srcAddr<span class="operator"> !=</span><span class="int"> 0</span><span class="operator">)</span>
strcpy<span class="operator">(</span>tempBuf<span class="operator">, (</span><span class="type">char</span><span class="operator"> *)</span>inet_ntoa<span class="operator">(</span>rtInfo<span class="operator">-></span>srcAddr<span class="operator">));</span><span class="flow">
else</span>
sprintf<span class="operator">(</span>tempBuf<span class="operator">,</span><span class="string">"*.*.*.*\t"</span><span class="operator">);</span>
fprintf<span class="operator">(</span>stdout<span class="operator">,</span><span class="string">"%s\n"</span><span class="operator">,</span> tempBuf<span class="operator">);
}</span><span class="type">
void</span> printGateway<span class="operator">()
{</span>
printf<span class="operator">(</span><span class="string">"%s\n"</span><span class="operator">,</span> gateway<span class="operator">);
}</span><span class="comment">
/* For parsing the route info returned */</span><span class="type">
void</span> parseRoutes<span class="operator">(</span><span class="keyword">struct</span> nlmsghdr<span class="operator"> *</span>nlHdr<span class="operator">,</span><span class="keyword"> struct</span> route_info<span class="operator"> *</span>rtInfo<span class="operator">)
{</span><span class="keyword">
struct</span> rtmsg<span class="operator"> *</span>rtMsg<span class="operator">;</span><span class="keyword">
struct</span> rtattr<span class="operator"> *</span>rtAttr<span class="operator">;</span><span class="type">
int</span> rtLen<span class="operator">;</span><span class="type">
char</span><span class="operator"> *</span>tempBuf<span class="operator"> =</span> NULL<span class="operator">;</span>
tempBuf<span class="operator"> = (</span><span class="type">char</span><span class="operator"> *)</span>malloc<span class="operator">(</span><span class="int">100</span><span class="operator">);</span>
rtMsg<span class="operator"> = (</span><span class="keyword">struct</span> rtmsg<span class="operator"> *)</span>NLMSG_DATA<span class="operator">(</span>nlHdr<span class="operator">);</span><span class="comment">
/* If the route is not for AF_INET or does not belong to main routing table
then return. */</span><span class="flow">
if</span><span class="operator">((</span>rtMsg<span class="operator">-></span>rtm_family<span class="operator"> !=</span> AF_INET<span class="operator">) || (</span>rtMsg<span class="operator">-></span>rtm_table<span class="operator"> !=</span> RT_TABLE_MAIN<span class="operator">))</span><span class="flow">
return</span><span class="operator">;</span><span class="comment">
/* get the rtattr field */</span>
rtAttr<span class="operator"> = (</span><span class="keyword">struct</span> rtattr<span class="operator"> *)</span>RTM_RTA<span class="operator">(</span>rtMsg<span class="operator">);</span>
rtLen<span class="operator"> =</span> RTM_PAYLOAD<span class="operator">(</span>nlHdr<span class="operator">);</span><span class="flow">
for</span><span class="operator">(;</span>RTA_OK<span class="operator">(</span>rtAttr<span class="operator">,</span>rtLen<span class="operator">);</span>rtAttr<span class="operator"> =</span> RTA_NEXT<span class="operator">(</span>rtAttr<span class="operator">,</span>rtLen<span class="operator">)){</span><span class="flow">
switch</span><span class="operator">(</span>rtAttr<span class="operator">-></span>rta_type<span class="operator">) {</span><span class="flow">
case</span> RTA_OIF<span class="operator">:</span>
if_indextoname<span class="operator">(*(</span><span class="type">int</span><span class="operator"> *)</span>RTA_DATA<span class="operator">(</span>rtAttr<span class="operator">),</span> rtInfo<span class="operator">-></span>ifName<span class="operator">);</span><span class="flow">
break</span><span class="operator">;</span><span class="flow">
case</span> RTA_GATEWAY<span class="operator">:</span>
rtInfo<span class="operator">-></span>gateWay<span class="operator">.</span>s_addr<span class="operator"> = *(</span>u_int<span class="operator"> *)</span>RTA_DATA<span class="operator">(</span>rtAttr<span class="operator">);</span><span class="flow">
break</span><span class="operator">;</span><span class="flow">
case</span> RTA_PREFSRC<span class="operator">:</span>
rtInfo<span class="operator">-></span>srcAddr<span class="operator">.</span>s_addr<span class="operator"> = *(</span>u_int<span class="operator"> *)</span>RTA_DATA<span class="operator">(</span>rtAttr<span class="operator">);</span><span class="flow">
break</span><span class="operator">;</span><span class="flow">
case</span> RTA_DST<span class="operator">:</span>
rtInfo<span class="operator">-></span>dstAddr<span class="operator">.</span>s_addr<span class="operator"> = *(</span>u_int<span class="operator"> *)</span>RTA_DATA<span class="operator">(</span>rtAttr<span class="operator">);</span><span class="flow">
break</span><span class="operator">;
}
}</span><span class="comment">
//printf("%s\n", (char *)inet_ntoa(rtInfo->dstAddr));
</span><span class="flow"> if</span><span class="operator"> (</span>strstr<span class="operator">((</span><span class="type">char</span><span class="operator"> *)</span>inet_ntoa<span class="operator">(</span>rtInfo<span class="operator">-></span>dstAddr<span class="operator">),</span><span class="string"> "0.0.0.0"</span><span class="operator">))</span>
sprintf<span class="operator">(</span>gateway<span class="operator">, (</span><span class="type">char</span><span class="operator"> *)</span>inet_ntoa<span class="operator">(</span>rtInfo<span class="operator">-></span>gateWay<span class="operator">));</span><span class="comment">
//printRoute(rtInfo);
</span> free<span class="operator">(</span>tempBuf<span class="operator">);</span><span class="flow">
return</span><span class="operator">;
}</span><span class="type">
int</span><span class="keyword"> main</span><span class="operator">()
{</span><span class="keyword">
struct</span> nlmsghdr<span class="operator"> *</span>nlMsg<span class="operator">;</span><span class="keyword">
struct</span> rtmsg<span class="operator"> *</span>rtMsg<span class="operator">;</span><span class="keyword">
struct</span> route_info<span class="operator"> *</span>rtInfo<span class="operator">;</span><span class="type">
char</span> msgBuf<span class="operator">[</span>BUFSIZE<span class="operator">];</span><span class="type">
int</span> sock<span class="operator">,</span> len<span class="operator">,</span> msgSeq<span class="operator"> =</span><span class="int"> 0</span><span class="operator">;</span><span class="type">
char</span> buff<span class="operator">[</span><span class="int">1024</span><span class="operator">];</span><span class="comment">
/* Create Socket */</span><span class="flow">
if</span><span class="operator">((</span>sock<span class="operator"> =</span> socket<span class="operator">(</span>PF_NETLINK<span class="operator">,</span> SOCK_DGRAM<span class="operator">,</span> NETLINK_ROUTE<span class="operator">)) <</span><span class="int"> 0</span><span class="operator">)</span>
perror<span class="operator">(</span><span class="string">"Socket Creation: "</span><span class="operator">);</span><span class="comment">
/* Initialize the buffer */</span>
memset<span class="operator">(</span>msgBuf<span class="operator">,</span><span class="int"> 0</span><span class="operator">,</span> BUFSIZE<span class="operator">);</span><span class="comment">
/* point the header and the msg structure pointers into the buffer */</span>
nlMsg<span class="operator"> = (</span><span class="keyword">struct</span> nlmsghdr<span class="operator"> *)</span>msgBuf<span class="operator">;</span>
rtMsg<span class="operator"> = (</span><span class="keyword">struct</span> rtmsg<span class="operator"> *)</span>NLMSG_DATA<span class="operator">(</span>nlMsg<span class="operator">);</span><span class="comment">
/* Fill in the nlmsg header*/</span>
nlMsg<span class="operator">-></span>nlmsg_len<span class="operator"> =</span> NLMSG_LENGTH<span class="operator">(</span><span class="keyword">sizeof</span><span class="operator">(</span><span class="keyword">struct</span> rtmsg<span class="operator">));</span><span class="comment"> // Length of message.
</span> nlMsg<span class="operator">-></span>nlmsg_type<span class="operator"> =</span> RTM_GETROUTE<span class="operator">;</span><span class="comment"> // Get the routes from kernel routing table .
</span>
nlMsg<span class="operator">-></span>nlmsg_flags<span class="operator"> =</span> NLM_F_DUMP<span class="operator"> |</span> NLM_F_REQUEST<span class="operator">;</span><span class="comment"> // The message is a request for dump.
</span> nlMsg<span class="operator">-></span>nlmsg_seq<span class="operator"> =</span> msgSeq<span class="operator">++;</span><span class="comment"> // Sequence of the message packet.
</span> nlMsg<span class="operator">-></span>nlmsg_pid<span class="operator"> =</span> getpid<span class="operator">();</span><span class="comment"> // PID of process sending the request.
</span><span class="comment">
/* Send the request */</span><span class="flow">
if</span><span class="operator">(</span>send<span class="operator">(</span>sock<span class="operator">,</span> nlMsg<span class="operator">,</span> nlMsg<span class="operator">-></span>nlmsg_len<span class="operator">,</span><span class="int"> 0</span><span class="operator">) <</span><span class="int"> 0</span><span class="operator">){</span>
printf<span class="operator">(</span><span class="string">"Write To Socket Failed...\n"</span><span class="operator">);</span><span class="flow">
return</span><span class="operator"> -</span><span class="int">1</span><span class="operator">;
}</span><span class="comment">
/* Read the response */</span><span class="flow">
if</span><span class="operator">((</span>len<span class="operator"> =</span> readNlSock<span class="operator">(</span>sock<span class="operator">,</span> msgBuf<span class="operator">,</span> msgSeq<span class="operator">,</span> getpid<span class="operator">())) <</span><span class="int"> 0</span><span class="operator">) {</span>
printf<span class="operator">(</span><span class="string">"Read From Socket Failed...\n"</span><span class="operator">);</span><span class="flow">
return</span><span class="operator"> -</span><span class="int">1</span><span class="operator">;
}</span><span class="comment">
/* Parse and print the response */</span>
rtInfo<span class="operator"> = (</span><span class="keyword">struct</span> route_info<span class="operator"> *)</span>malloc<span class="operator">(</span><span class="keyword">sizeof</span><span class="operator">(</span><span class="keyword">struct</span> route_info<span class="operator">));</span><span class="comment">
/* THIS IS THE NETTSTAT -RL code I commented out the printing here and in parse routes */</span><span class="comment">
//fprintf(stdout, "Destination\tGateway\tInterface\tSource\n");
</span><span class="flow"> for</span><span class="operator">(;</span>NLMSG_OK<span class="operator">(</span>nlMsg<span class="operator">,</span>len<span class="operator">);</span>nlMsg<span class="operator"> =</span> NLMSG_NEXT<span class="operator">(</span>nlMsg<span class="operator">,</span>len<span class="operator">)){</span>
memset<span class="operator">(</span>rtInfo<span class="operator">,</span><span class="int"> 0</span><span class="operator">,</span><span class="keyword"> sizeof</span><span class="operator">(</span><span class="keyword">struct</span> route_info<span class="operator">));</span>
parseRoutes<span class="operator">(</span>nlMsg<span class="operator">,</span> rtInfo<span class="operator">);
}</span>
free<span class="operator">(</span>rtInfo<span class="operator">);</span>
close<span class="operator">(</span>sock<span class="operator">);</span>
printGateway<span class="operator">();</span><span class="flow">
return</span><span class="int"> 0</span><span class="operator">;
}</span>
</pre>
</pre>
</div>
</div>
samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-76397043280343391502010-09-14T22:11:00.000-07:002010-09-15T02:52:27.676-07:00Using socket RAW to send an ICMP protocal<div style="margin: 5px 20px 20px;"><div class="smallfont" style="margin-bottom: 2px;">this is a simple program that i found on the internet showing how to send ICMP using RAW socket.</div>example code:<br />
<div><pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 0px; padding: 6px; overflow: auto; width: 650px; height: 400px; text-align: left;"><font color="#444444">/*
* pinger.c
* This is a ping imitation program
* It will send an ICMP ECHO packet to the server of
* your choice and listen for an ICMP REPLY packet
* Have fun!
*/</font>
<font color="#444444">/*
* pinger.c
* This is a ping imitation program
* It will send an ICMP ECHO packet to the server of
* your choice and listen for an ICMP REPLY packet
* Have fun!
*/</font>
<font color="0000ff"><strong>#include <font color="#008000"><stdio.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><stdlib.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><sys/types.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><sys/socket.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><netinet/in.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><arpa/inet.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><netdb.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><linux/ip.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><linux/icmp.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><string.h></font></strong></font>
<font color="0000ff"><strong>#include <font color="#008000"><unistd.h></font></strong></font>
<strong>char</strong> <font color="#2040a0">dst_addr</font><font color="4444FF">[</font><font color="#FF0000">15</font><font color="4444FF">]</font><font color="4444FF">;</font>
<strong>char</strong> <font color="#2040a0">src_addr</font><font color="4444FF">[</font><font color="#FF0000">15</font><font color="4444FF">]</font><font color="4444FF">;</font>
<strong>unsigned</strong> <strong>short</strong> <font color="#2040a0">in_cksum</font><font color="4444FF">(</font><strong>unsigned</strong> <strong>short</strong> <font color="4444FF">*</font>, <strong>int</strong><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>void</strong> <font color="#2040a0">parse_argvs</font><font color="4444FF">(</font><strong>char</strong><font color="4444FF">*</font><font color="4444FF">*</font>, <strong>char</strong><font color="4444FF">*</font>, <strong>char</strong><font color="4444FF">*</font> <font color="4444FF">)</font><font color="4444FF">;</font>
<strong>void</strong> <font color="#2040a0">usage</font><font color="4444FF">(</font><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>char</strong><font color="4444FF">*</font> <font color="#2040a0">getip</font><font color="4444FF">(</font><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>int</strong> <font color="#2040a0">main</font><font color="4444FF">(</font><strong>int</strong> <font color="#2040a0">argc</font>, <strong>char</strong><font color="4444FF">*</font> <font color="#2040a0">argv</font><font color="4444FF">[</font><font color="4444FF">]</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">*</font> <font color="#2040a0">ip</font><font color="4444FF">;</font>
<strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">*</font> <font color="#2040a0">ip_reply</font><font color="4444FF">;</font>
<strong>struct</strong> <font color="#2040a0">icmphdr</font><font color="4444FF">*</font> <font color="#2040a0">icmp</font><font color="4444FF">;</font>
<strong>struct</strong> <font color="#2040a0">sockaddr_in</font> <font color="#2040a0">connection</font><font color="4444FF">;</font>
<strong>char</strong><font color="4444FF">*</font> <font color="#2040a0">packet</font><font color="4444FF">;</font>
<strong>char</strong><font color="4444FF">*</font> <font color="#2040a0">buffer</font><font color="4444FF">;</font>
<strong>int</strong> <font color="#2040a0">sockfd</font><font color="4444FF">;</font>
<strong>int</strong> <font color="#2040a0">optval</font><font color="4444FF">;</font>
<strong>int</strong> <font color="#2040a0">addrlen</font><font color="4444FF">;</font>
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">getuid</font><font color="4444FF">(</font><font color="4444FF">)</font> <font color="4444FF">!</font><font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#2040a0">fprintf</font><font color="4444FF">(</font><font color="#2040a0">stderr</font>, <font color="#008000">"%s: root privelidges needed<font color="#77dd77">\n</font>"</font>, <font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#FF0000">0</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">exit</font><font color="4444FF">(</font><font color="#2040a0">EXIT_FAILURE</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<font color="#2040a0">parse_argvs</font><font color="4444FF">(</font><font color="#2040a0">argv</font>, <font color="#2040a0">dst_addr</font>, <font color="#2040a0">src_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">printf</font><font color="4444FF">(</font><font color="#008000">"Source address: %s<font color="#77dd77">\n</font>"</font>, <font color="#2040a0">src_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">printf</font><font color="4444FF">(</font><font color="#008000">"Destination address: %s<font color="#77dd77">\n</font>"</font>, <font color="#2040a0">dst_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#444444">/*
* allocate all necessary memory
*/</font>
<font color="#2040a0">ip</font> <font color="4444FF">=</font> <font color="#2040a0">malloc</font><font color="4444FF">(</font><strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">ip_reply</font> <font color="4444FF">=</font> <font color="#2040a0">malloc</font><font color="4444FF">(</font><strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">icmp</font> <font color="4444FF">=</font> <font color="#2040a0">malloc</font><font color="4444FF">(</font><strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">icmphdr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">packet</font> <font color="4444FF">=</font> <font color="#2040a0">malloc</font><font color="4444FF">(</font><strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">)</font> <font color="4444FF">+</font> <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">icmphdr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">buffer</font> <font color="4444FF">=</font> <font color="#2040a0">malloc</font><font color="4444FF">(</font><strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">)</font> <font color="4444FF">+</font> <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">icmphdr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#444444"><i>/****************************************************************/</i></font>
<font color="#2040a0">ip</font> <font color="4444FF">=</font> <font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">*</font><font color="4444FF">)</font> <font color="#2040a0">packet</font><font color="4444FF">;</font>
<font color="#2040a0">icmp</font> <font color="4444FF">=</font> <font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">icmphdr</font><font color="4444FF">*</font><font color="4444FF">)</font> <font color="4444FF">(</font><font color="#2040a0">packet</font> <font color="4444FF">+</font> <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#444444">/*
* here the ip packet is set up except checksum
*/</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">ihl</font> <font color="4444FF">=</font> <font color="#FF0000">5</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">version</font> <font color="4444FF">=</font> <font color="#FF0000">4</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">tos</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">tot_len</font> <font color="4444FF">=</font> <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">)</font> <font color="4444FF">+</font> <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">icmphdr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">id</font> <font color="4444FF">=</font> <font color="#2040a0">htons</font><font color="4444FF">(</font><font color="#2040a0">random</font><font color="4444FF">(</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">ttl</font> <font color="4444FF">=</font> <font color="#FF0000">255</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">protocol</font> <font color="4444FF">=</font> <font color="#2040a0">IPPROTO_ICMP</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">saddr</font> <font color="4444FF">=</font> <font color="#2040a0">inet_addr</font><font color="4444FF">(</font><font color="#2040a0">src_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">daddr</font> <font color="4444FF">=</font> <font color="#2040a0">inet_addr</font><font color="4444FF">(</font><font color="#2040a0">dst_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>if</strong> <font color="4444FF">(</font><font color="4444FF">(</font><font color="#2040a0">sockfd</font> <font color="4444FF">=</font> <font color="#2040a0">socket</font><font color="4444FF">(</font><font color="#2040a0">AF_INET</font>, <font color="#2040a0">SOCK_RAW</font>, <font color="#2040a0">IPPROTO_ICMP</font><font color="4444FF">)</font><font color="4444FF">)</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="4444FF">-</font><font color="#FF0000">1</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#2040a0">perror</font><font color="4444FF">(</font><font color="#008000">"socket"</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">exit</font><font color="4444FF">(</font><font color="#2040a0">EXIT_FAILURE</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<font color="#444444">/*
* IP_HDRINCL must be set on the socket so that
* the kernel does not attempt to automatically add
* a default ip header to the packet
*/</font>
<font color="#2040a0">setsockopt</font><font color="4444FF">(</font><font color="#2040a0">sockfd</font>, <font color="#2040a0">IPPROTO_IP</font>, <font color="#2040a0">IP_HDRINCL</font>, <font color="4444FF">&</font><font color="#2040a0">optval</font>, <strong>sizeof</strong><font color="4444FF">(</font><strong>int</strong><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#444444">/*
* here the icmp packet is created
* also the ip checksum is generated
*/</font>
<font color="#2040a0">icmp</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">type</font> <font color="4444FF">=</font> <font color="#2040a0">ICMP_ECHO</font><font color="4444FF">;</font>
<font color="#2040a0">icmp</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">code</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
<font color="#2040a0">icmp</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">un</font>.<font color="#2040a0">echo</font>.<font color="#2040a0">id</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
<font color="#2040a0">icmp</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">un</font>.<font color="#2040a0">echo</font>.<font color="#2040a0">sequence</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
<font color="#2040a0">icmp</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">checksum</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
<font color="#2040a0">icmp</font><font color="4444FF">-</font><font color="4444FF">></font> <font color="#2040a0">checksum</font> <font color="4444FF">=</font> <font color="#2040a0">in_cksum</font><font color="4444FF">(</font><font color="4444FF">(</font><strong>unsigned</strong> <strong>short</strong> <font color="4444FF">*</font><font color="4444FF">)</font><font color="#2040a0">icmp</font>, <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">icmphdr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">check</font> <font color="4444FF">=</font> <font color="#2040a0">in_cksum</font><font color="4444FF">(</font><font color="4444FF">(</font><strong>unsigned</strong> <strong>short</strong> <font color="4444FF">*</font><font color="4444FF">)</font><font color="#2040a0">ip</font>, <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">connection</font>.<font color="#2040a0">sin_family</font> <font color="4444FF">=</font> <font color="#2040a0">AF_INET</font><font color="4444FF">;</font>
<font color="#2040a0">connection</font>.<font color="#2040a0">sin_addr</font>.<font color="#2040a0">s_addr</font> <font color="4444FF">=</font> <font color="#2040a0">inet_addr</font><font color="4444FF">(</font><font color="#2040a0">dst_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#444444">/*
* now the packet is sent
*/</font>
<font color="#2040a0">sendto</font><font color="4444FF">(</font><font color="#2040a0">sockfd</font>, <font color="#2040a0">packet</font>, <font color="#2040a0">ip</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">tot_len</font>, <font color="#FF0000">0</font>, <font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">sockaddr</font> <font color="4444FF">*</font><font color="4444FF">)</font><font color="4444FF">&</font><font color="#2040a0">connection</font>, <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">sockaddr</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">printf</font><font color="4444FF">(</font><font color="#008000">"Sent %d byte packet to %s<font color="#77dd77">\n</font>"</font>, <strong>sizeof</strong><font color="4444FF">(</font><font color="#2040a0">packet</font><font color="4444FF">)</font>, <font color="#2040a0">dst_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#444444">/*
* now we listen for responses
*/</font>
<font color="#2040a0">addrlen</font> <font color="4444FF">=</font> <strong>sizeof</strong><font color="4444FF">(</font><font color="#2040a0">connection</font><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">recvfrom</font><font color="4444FF">(</font><font color="#2040a0">sockfd</font>, <font color="#2040a0">buffer</font>, <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">)</font> <font color="4444FF">+</font> <strong>sizeof</strong><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">icmphdr</font><font color="4444FF">)</font>, <font color="#FF0000">0</font>, <font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">sockaddr</font> <font color="4444FF">*</font><font color="4444FF">)</font><font color="4444FF">&</font><font color="#2040a0">connection</font>, <font color="4444FF">&</font><font color="#2040a0">addrlen</font><font color="4444FF">)</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="4444FF">-</font><font color="#FF0000">1</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#2040a0">perror</font><font color="4444FF">(</font><font color="#008000">"recv"</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<strong>else</strong>
<font color="4444FF"><strong>{</strong></font>
<font color="#2040a0">printf</font><font color="4444FF">(</font><font color="#008000">"Received %d byte reply from %s:<font color="#77dd77">\n</font>"</font>, <strong>sizeof</strong><font color="4444FF">(</font><font color="#2040a0">buffer</font><font color="4444FF">)</font>, <font color="#2040a0">dst_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">ip_reply</font> <font color="4444FF">=</font> <font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">iphdr</font><font color="4444FF">*</font><font color="4444FF">)</font> <font color="#2040a0">buffer</font><font color="4444FF">;</font>
<font color="#2040a0">printf</font><font color="4444FF">(</font><font color="#008000">"ID: %d<font color="#77dd77">\n</font>"</font>, <font color="#2040a0">ntohs</font><font color="4444FF">(</font><font color="#2040a0">ip_reply</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">id</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">printf</font><font color="4444FF">(</font><font color="#008000">"TTL: %d<font color="#77dd77">\n</font>"</font>, <font color="#2040a0">ip_reply</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">ttl</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<font color="#2040a0">close</font><font color="4444FF">(</font><font color="#2040a0">sockfd</font><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>return</strong> <font color="#FF0000">0</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<strong>void</strong> <font color="#2040a0">parse_argvs</font><font color="4444FF">(</font><strong>char</strong><font color="4444FF">*</font><font color="4444FF">*</font> <font color="#2040a0">argv</font>, <strong>char</strong><font color="4444FF">*</font> <font color="#2040a0">dst</font>, <strong>char</strong><font color="4444FF">*</font> <font color="#2040a0">src</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<strong>int</strong> <font color="#2040a0">i</font><font color="4444FF">;</font>
<strong>if</strong><font color="4444FF">(</font><font color="4444FF">!</font><font color="4444FF">(</font><font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#FF0000">1</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#444444">/* there are no options on the command line */</font>
<font color="#2040a0">usage</font><font color="4444FF">(</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">exit</font><font color="4444FF">(</font><font color="#2040a0">EXIT_FAILURE</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<strong>if</strong> <font color="4444FF">(</font><font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#FF0000">1</font><font color="4444FF">)</font> <font color="4444FF">&</font><font color="4444FF">&</font> <font color="4444FF">(</font><font color="4444FF">!</font><font color="4444FF">(</font><font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#FF0000">2</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#444444">/*
* only one argument provided
* assume it is the destination server
* source address is local host
*/</font>
<font color="#2040a0">strncpy</font><font color="4444FF">(</font><font color="#2040a0">dst</font>, <font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#FF0000">1</font><font color="4444FF">)</font>, <font color="#FF0000">15</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">strncpy</font><font color="4444FF">(</font><font color="#2040a0">src</font>, <font color="#2040a0">getip</font><font color="4444FF">(</font><font color="4444FF">)</font>, <font color="#FF0000">15</font><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>return</strong><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<strong>else</strong> <strong>if</strong> <font color="4444FF">(</font><font color="4444FF">(</font><font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#FF0000">1</font><font color="4444FF">)</font> <font color="4444FF">&</font><font color="4444FF">&</font> <font color="4444FF">(</font><font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#FF0000">2</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">)</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#444444">/*
* both the destination and source address are defined
* for now only implemented is a source address and
* destination address
*/</font>
<font color="#2040a0">strncpy</font><font color="4444FF">(</font><font color="#2040a0">dst</font>, <font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#FF0000">1</font><font color="4444FF">)</font>, <font color="#FF0000">15</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">i</font> <font color="4444FF">=</font> <font color="#FF0000">2</font><font color="4444FF">;</font>
<strong>while</strong><font color="4444FF">(</font><font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#2040a0">i</font> <font color="4444FF">+</font> <font color="#FF0000">1</font><font color="4444FF">)</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">strncmp</font><font color="4444FF">(</font><font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#2040a0">i</font><font color="4444FF">)</font>, <font color="#008000">"-s"</font>, <font color="#FF0000">2</font><font color="4444FF">)</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#2040a0">strncpy</font><font color="4444FF">(</font><font color="#2040a0">src</font>, <font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">argv</font> <font color="4444FF">+</font> <font color="#2040a0">i</font> <font color="4444FF">+</font> <font color="#FF0000">1</font><font color="4444FF">)</font>, <font color="#FF0000">15</font><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>break</strong><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<font color="#2040a0">i</font><font color="4444FF">+</font><font color="4444FF">+</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<font color="4444FF"><strong>}</strong></font>
<font color="4444FF"><strong>}</strong></font>
<strong>void</strong> <font color="#2040a0">usage</font><font color="4444FF">(</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#2040a0">fprintf</font><font color="4444FF">(</font><font color="#2040a0">stderr</font>, <font color="#008000">"<font color="#77dd77">\n</font>Usage: pinger [destination] <-s [source]><font color="#77dd77">\n</font>"</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">fprintf</font><font color="4444FF">(</font><font color="#2040a0">stderr</font>, <font color="#008000">"Destination must be provided<font color="#77dd77">\n</font>"</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">fprintf</font><font color="4444FF">(</font><font color="#2040a0">stderr</font>, <font color="#008000">"Source is optional<font color="#77dd77">\n</font><font color="#77dd77">\n</font>"</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<strong>char</strong><font color="4444FF">*</font> <font color="#2040a0">getip</font><font color="4444FF">(</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<strong>char</strong> <font color="#2040a0">buffer</font><font color="4444FF">[</font><font color="#FF0000">256</font><font color="4444FF">]</font><font color="4444FF">;</font>
<strong>struct</strong> <font color="#2040a0">hostent</font><font color="4444FF">*</font> <font color="#2040a0">h</font><font color="4444FF">;</font>
<font color="#2040a0">gethostname</font><font color="4444FF">(</font><font color="#2040a0">buffer</font>, <font color="#FF0000">256</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="#2040a0">h</font> <font color="4444FF">=</font> <font color="#2040a0">gethostbyname</font><font color="4444FF">(</font><font color="#2040a0">buffer</font><font color="4444FF">)</font><font color="4444FF">;</font>
<strong>return</strong> <font color="#2040a0">inet_ntoa</font><font color="4444FF">(</font><font color="4444FF">*</font><font color="4444FF">(</font><strong>struct</strong> <font color="#2040a0">in_addr</font> <font color="4444FF">*</font><font color="4444FF">)</font><font color="#2040a0">h</font><font color="4444FF">-</font><font color="4444FF">></font><font color="#2040a0">h_addr</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<font color="#444444">/*
* in_cksum --
* Checksum routine for Internet Protocol
* family headers (C Version)
*/</font>
<strong>unsigned</strong> <strong>short</strong> <font color="#2040a0">in_cksum</font><font color="4444FF">(</font><strong>unsigned</strong> <strong>short</strong> <font color="4444FF">*</font><font color="#2040a0">addr</font>, <strong>int</strong> <font color="#2040a0">len</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<strong>register</strong> <strong>int</strong> <font color="#2040a0">sum</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
<font color="#2040a0">u_short</font> <font color="#2040a0">answer</font> <font color="4444FF">=</font> <font color="#FF0000">0</font><font color="4444FF">;</font>
<strong>register</strong> <font color="#2040a0">u_short</font> <font color="4444FF">*</font><font color="#2040a0">w</font> <font color="4444FF">=</font> <font color="#2040a0">addr</font><font color="4444FF">;</font>
<strong>register</strong> <strong>int</strong> <font color="#2040a0">nleft</font> <font color="4444FF">=</font> <font color="#2040a0">len</font><font color="4444FF">;</font>
<font color="#444444">/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/</font>
<strong>while</strong> <font color="4444FF">(</font><font color="#2040a0">nleft</font> <font color="4444FF">></font> <font color="#FF0000">1</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="#2040a0">sum</font> <font color="4444FF">+</font><font color="4444FF">=</font> <font color="4444FF">*</font><font color="#2040a0">w</font><font color="4444FF">+</font><font color="4444FF">+</font><font color="4444FF">;</font>
<font color="#2040a0">nleft</font> <font color="4444FF">-</font><font color="4444FF">=</font> <font color="#FF0000">2</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<font color="#444444">/* mop up an odd byte, if necessary */</font>
<strong>if</strong> <font color="4444FF">(</font><font color="#2040a0">nleft</font> <font color="4444FF">=</font><font color="4444FF">=</font> <font color="#FF0000">1</font><font color="4444FF">)</font>
<font color="4444FF"><strong>{</strong></font>
<font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">u_char</font> <font color="4444FF">*</font><font color="4444FF">)</font> <font color="4444FF">(</font><font color="4444FF">&</font><font color="#2040a0">answer</font><font color="4444FF">)</font> <font color="4444FF">=</font> <font color="4444FF">*</font><font color="4444FF">(</font><font color="#2040a0">u_char</font> <font color="4444FF">*</font><font color="4444FF">)</font> <font color="#2040a0">w</font><font color="4444FF">;</font>
<font color="#2040a0">sum</font> <font color="4444FF">+</font><font color="4444FF">=</font> <font color="#2040a0">answer</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
<font color="#444444">/* add back carry outs from top 16 bits to low 16 bits */</font>
<font color="#2040a0">sum</font> <font color="4444FF">=</font> <font color="4444FF">(</font><font color="#2040a0">sum</font> <font color="4444FF">></font><font color="4444FF">></font> <font color="#FF0000">16</font><font color="4444FF">)</font> <font color="4444FF">+</font> <font color="4444FF">(</font><font color="#2040a0">sum</font> <font color="4444FF">&</font> <font color="#FF0000">0xffff</font><font color="4444FF">)</font><font color="4444FF">;</font> <font color="#444444">/* add hi 16 to low 16 */</font>
<font color="#2040a0">sum</font> <font color="4444FF">+</font><font color="4444FF">=</font> <font color="4444FF">(</font><font color="#2040a0">sum</font> <font color="4444FF">></font><font color="4444FF">></font> <font color="#FF0000">16</font><font color="4444FF">)</font><font color="4444FF">;</font> <font color="#444444">/* add carry */</font>
<font color="#2040a0">answer</font> <font color="4444FF">=</font> ~<font color="#2040a0">sum</font><font color="4444FF">;</font> <font color="#444444">/* truncate to 16 bits */</font>
<strong>return</strong> <font color="4444FF">(</font><font color="#2040a0">answer</font><font color="4444FF">)</font><font color="4444FF">;</font>
<font color="4444FF"><strong>}</strong></font>
</pre></div><br />
<br />
</div>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-50401688882426832642010-05-03T05:52:00.000-07:002010-05-03T21:21:25.019-07:00Stopping TCP retransmitThe <a href="http://samuelogre.blogspot.com/2009/12/socket-keep-alive-time.html">TCP keep-alive</a> is a great way to detect TCP connection lost; if a connection list lost, "select()" will show readable data, yet the data length returned by "recv()" is less or equal to zero. Yet, if you've already sent a data during the connection lost, the TCP retransmit is triggered, stopping the mechanism of TCP keep-alive, the bad news is that the retransmit time can go on to 15-20 mins, and keep-alive will not be invoked during this time period.<br />
In other words, you will not notice the connection lost unless you full the Tx buffer of the net device driver(the default size is 4096 bytes).<br />
If you have little or no data to send, detecting the connection loss will take forever, and become a pain in the ass. <br />
To solve this issue,you can reduce the tcp retransmit times by doing:<br />
system("sysctl -w net.ipv4.tcp_retries1=2");<br />
system("sysctl -w net.ipv4.tcp_retries2=3");<br />
<br />
yet the effect is system wide.... not a very elegant solution.<br />
<br />
P.S.<br />
It was interesting to find out that linux socket always tries to send every packet, even if "netif_queue_stopped(netdev *)" (used for flow control on the Tx side of the driver) or "netif_carrier_off(netdev *)"(used when carrier is down ex. unplugged cable) is called by the net device driver, Linux queues the unsent packets and sends it the instance when carrier or queue is available. This mechanism guarantees the message you sent is delivered to the destination if possible.samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-41236842344738792502009-12-25T01:34:00.000-08:002010-09-12T20:49:43.475-07:00socket keep alive time<div style="margin: 5px 20px 20px;"><div class="smallfont" style="margin-bottom: 2px;">You might know that,while setting up a TCP connection you can enable SO_KEEPALIVE, forcing the system to check on the connection routinely to see if the connection is still there, not broken by the any connection issues or so.<br />
Yet, have you ever wondered, how often does the system go through this connection check?<br />
This is how we change "keep alive time" for individual socket on linux systems, otherwise the system checks for the connection every 30 mins or so, by default, which is usually too long.<br />
Notice: this is not a standard socket operation, which may not be used on other operating systems. (for example: windows)<br />
Code:</div><pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 0px; padding: 6px; overflow: auto; width: 650px; height: 400px; text-align: left;">int keepAlive = 1;
// set timeout params for SO_KEEPALIVE
keepTime = 5; //the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe
keepProbe = 1; //number of retry
keepInvl = 1; //the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime
if( setsockopt(cliSocket, SOL_TCP, TCP_KEEPIDLE, &keepTime, sizeof(keepTime)) == -1
||setsockopt(cliSocket, SOL_TCP, TCP_KEEPCNT, &keepProbe, sizeof(keepProbe)) == -1
||setsockopt(cliSocket, SOL_TCP, TCP_KEEPINTVL, &keepInvl, sizeof(keepInvl)) == -1
||setsockopt(cliSocket,SOL_SOCKET,SO_KEEPALIVE, &keepAlive,sizeof(keepAlive)) == -1)
{
printf("Socket %d setKeepAlive timeout failed.\n", cliSocket);
close(cliSocket);
}
</pre></div>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-7655159000410035352009-12-24T20:32:00.000-08:002012-09-12T19:50:13.099-07:00enalbing connect() to timeout This is a very useful technique that you should try out while you are starting up a tcp connection.<br />
Instead of "breaking out on error" or being "blocked" at the point of "connect() " when the remote server is temporary unavalible, this function will try to connect in a given period of time.<br />
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">
Code:</div>
<pre class="alt2" dir="ltr" style="border: 1px inset; height: 1400px; margin: 0px; overflow: auto; padding: 6px; text-align: left; width: 650px;">void connect_w_to(void) {
int res;
struct sockaddr_in addr;
long arg;
fd_set myset;
struct timeval tv;
int valopt;
socklen_t lon;
// Create socket
soc = socket(AF_INET, SOCK_STREAM, 0);
if (soc < 0) {
fprintf(stderr, "Error creating socket (%d %s)\n", errno, strerror(errno));
exit(0);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(2000);
addr.sin_addr.s_addr = inet_addr("192.168.0.1");
// Set non-blocking
if( (arg = fcntl(soc, F_GETFL, NULL)) < 0) {
fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
exit(0);
}
arg |= O_NONBLOCK;
if( fcntl(soc, F_SETFL, arg) < 0) {
fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
exit(0);
}
// Trying to connect with timeout
res = connect(soc, (struct sockaddr *)&addr, sizeof(addr));
if (res < 0) {
if (errno == EINPROGRESS) {
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
do {
tv.tv_sec = 15;
tv.tv_usec = 0;
FD_ZERO(&myset);
FD_SET(soc, &myset);
res = select(soc+1, NULL, &myset, NULL, &tv);
if (res < 0 && errno != EINTR) {
fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
exit(0);
}
else if (res > 0) {
// Socket selected for write
lon = sizeof(int);
if (getsockopt(soc, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
fprintf(stderr, "Error in getsockopt() %d - %s\n", errno, strerror(errno));
exit(0);
}
// Check the value returned...
if (valopt) {
fprintf(stderr, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt)
);
exit(0);
}
break;
}
else {
fprintf(stderr, "Timeout in select() - Cancelling!\n");
exit(0);
}
} while (1);
}
else {
fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
exit(0);
}
}
// Set to blocking mode again...
if( (arg = fcntl(soc, F_GETFL, NULL)) < 0) {
fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));
exit(0);
}
arg &= (~O_NONBLOCK);
if( fcntl(soc, F_SETFL, arg) < 0) {
fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));
exit(0);
}
// I hope that is all
}</pre>
</div>
<div style="margin: 5px 20px 20px;">
</div>
samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-59773207021797833562008-12-22T08:35:00.000-08:002009-01-04T06:50:43.751-08:00google patent search還記得我以前在學習專利的時候<br />要花很多時間和USPTO緩慢的搜索引擎掙扎<br />花了很多時間也不一定可以找到好的關鍵字<br />今天 我豁然之間發現google也有搜尋專利的功能了<br />真是太方便了...<br /><a href="http://www.google.com/patents">www.google.com/patents</a><br />Google makes life easier every day...samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-48221787916303445572008-11-22T06:35:00.000-08:002008-11-22T21:31:00.439-08:00GNU debugI've been reading tutorials about gdb, and find it as very handy tool while debugging...<br />It comes out that you can set breaking points, watching points, access and change variables inside memory. That makes debugging so much easier than ever before.<br />here are some really useful websites that would really help out, if you would like to learn more about gdb, including two tutorials and a simple user manual.<br /><a href="http://www.cmlab.csie.ntu.edu.tw/%7Edaniel/linux/gdb.html">GDB - GNU debugger</a><br /><a href="http://www.cs.usyd.edu.au/%7Esholden/TEACHING/PP/2000sem2/TUTES/week7/gdb.html">gdb Tutorial</a><br /><a href="http://www.dirac.org/linux/gdb/">Peter's gdb Tutorial: Table Of Contents</a>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-30672560490048230602008-08-01T01:40:00.000-07:002008-08-01T01:43:08.721-07:00法國家鄉馬鈴薯切丁未去皮的馬鈴薯<br />配上切碎的百里香<br />灑上黑胡椒 白胡椒 海鹽 西班牙紅醬<br />在預熱250度C的烤箱內烤熟<br /><br />味道超好samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-4413071016149029672008-07-30T17:21:00.000-07:002008-07-30T17:48:02.577-07:00涼拌鮮蝦葡萄柚和姑姑到士林的TOROS吃東西<br />吃到一個好吃的沙拉<br />回來 找到他的食譜<br /><br />材料:<br /><br />1.蝦子數條 2.葡萄柚一顆 3.檸檬半顆 4.新鮮檸檬百里香少許<br />調味料:<br /><br />1. 鹽 2.糖 3.橄欖油 4.白胡椒<br /><br /><br />作法:<br /><br />1.蝦子放入滾水煮熟,蝦殼剝掉備用<br /><br />2.將葡萄柚從中剖半,但果肉不要傷到,這裡需要小心一些,取出完整果肉<br /><br />3.將葡萄柚剝成瓣狀備用<br /><br />4.取一碗,將檸檬汁及所有調味料混合均勻<br /><br />5.將蝦仁、葡萄柚果肉及調味料拌勻後,擺盤,最後用百里香裝飾一下即可。samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-29716341550912336872008-07-19T07:38:00.000-07:002008-07-19T07:43:25.477-07:00美式鬆餅以前想要自己做一份美式早餐鬆餅<br />都必須要先賣一包很貴很貴的鬆餅粉<br />有了這份食譜之後 就可以用麵粉還有泡打粉自己做出鬆餅粉了<br /><br /><span style="font-family:標楷體;font-size:130%;"><strong><span style="background-color: rgb(204, 255, 255);" ><u>食材</u></span></strong></span> <div><span style="font-family:標楷體;font-size:130%;"><br />1.<br />低筋麵粉...........160g<br /><span><span></span></span></span></div> <div><span style="font-family:標楷體;font-size:130%;">2.<br />泡打粉.............6g<br />3.<br /><span><span></span></span></span></div><span style="font-family:標楷體;font-size:130%;">奶油...............15g<br />4.<br />砂糖...............50g<br />5.<br />鹽.................1g<br />6.<br />牛奶(或水).........175g<br />7.<br />雞蛋...............2個<br />8.<br />楓糖...............適量<br /><br />份量:10片<br /><br /><br /></span><span style="font-family:標楷體;font-size:130%;"><u><strong><span style="background-color: rgb(204, 255, 255);" >作法<br /></span></strong></u></span><br /><span style="font-family:標楷體;font-size:130%;">1.<br />先將奶油放置室溫放軟,用加熱的方式也可以。<br />將低筋麵粉跟泡打粉過篩混和後備用。<br /></span><span style="font-family:標楷體;font-size:130%;"><br />2.<br />把糖、鹽</span><span style="font-family:標楷體;font-size:130%;">、</span><span style="font-family:標楷體;font-size:130%;">奶油加入麵粉中,牛奶分兩次加入攪拌均勻。<br />再把雞蛋打散攪拌後,加入麵糊裡一起攪拌均勻。<br /></span><span style="font-family:標楷體;font-size:130%;">3.<br />先將鍋子預熱後,舀定量的麵糊到鍋子上煎。<br />我是用不沾的平底鍋,所以我開小火不放油乾煎。<br />等表面充滿氣泡後,就可以翻面了,翻面之後再煎20秒即可。<br /></span><span style="font-family:標楷體;font-size:130%;">4.<br />將煎好的pancake疊成層狀,淋上楓糖</span><span style="font-family:標楷體;font-size:130%;">、</span><span style="font-family:標楷體;font-size:130%;">果醬</span><span style="font-family:標楷體;font-size:130%;">、</span><span style="font-family:標楷體;font-size:130%;">鮮奶油即可。<br /><br /><br /></span>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-38770906619032154482008-07-12T11:21:00.000-07:002008-07-14T00:06:47.974-07:00炸豬排材料:<br /><br />豬排肉片四片(一片約60公克)<br />可選用梅花肉或豬里肌肉 比較軟嫩<br /><br />A:醬油二茶匙<br /><br /> 醬油膏一茶匙<br /><br /> 米酒一茶匙<br /><br /> 蒜末少許<br />B<br /> 蛋液 半顆<br /><br /> 麵粉一湯匙<br />C<br /> 麵包粉適量<br />````````````````````````````````````````````````````<br />做法:<br /><br />將豬肉肉片以刀拍幾下 可以使肉片組織鬆弛<br /><br />並且增加面積 在使用叉子叉正反面 可以使肉更容易吸收醬料<br /><br />並且更加柔軟<br /><br />在將A料混合均勻 塗抹在肉片上 此處醃料很少<br /><br />因為主要是做日式風味 所以口味不重<br /><br />將B即半顆蛋的蛋液加上一湯匙的麵粉混勻<br /><br />將醃好的肉片沾上B料<br /><br />在沾上麵包粉<br /><br />沾好之後放置一段時間讓麵包粉可以回潮<br /><br />這樣在炸的時候比較不會皮肉分離<br /><br />起油鍋<br />讓豬肉在油鍋裡快樂的油炸<br /><br />油炸到淡淡金黃色時就拿起來 不要炸到太金黃<br /><br />起鍋後放置約五分鐘 即可食用samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-31644651454162190172008-07-11T03:17:00.000-07:002008-07-12T06:30:22.189-07:00c++ and c 有用的工具c++/c reference:<br /><a href="http://www.cplusplus.com/reference/clibrary/cstdlib/atoi.html">http://www.cplusplus.com/reference/clibrary/cstdlib/atoi.html</a><br />當看別人的code 的時候<br />常常會遇到別人習慣的function和我所用的不同<br />這個網站提供很方便的查詢,說明,所在的h file<br /><br />pthread API user guide and manual:<br /><a href="http://cs.pub.ro/%7Eapc/2003/resources/pthreads/uguide/users-96.htm">http://cs.pub.ro/~apc/2003/resources/pthreads/uguide/users-96.htm</a><br />while multi-thread programming 這個網站也提供很棒的reference...samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-40570926777097611392008-07-09T05:38:00.000-07:002008-07-09T23:39:17.620-07:00味增淋醬味增淋醬:<br />紅味增 1大匙<br />白味增 1/2大匙<br />味霖 1大匙<br />醬油 1匙<br />糖 1匙<br />水 1碗<br />洋蔥碎1/4顆<br />太白粉 適量<br /><br /><span style="font-size: 10pt; font-family: 新細明體;"><span style="color:#000000;">味增醬調好備用,取一鍋子,將奶油融化後,下洋蔥炒軟,再將調好的味增醬倒入鍋中用小火煮開,等香味出來後即可用太白粉水勾薄芡</span></span><br /><br />reference:<br /><a href="http://blog.pixnet.net/janeliusy/post/6302769">http://blog.pixnet.net/janeliusy/post/6302769</a><br /><p></p><p align="left"></p>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-22381686475661348422008-07-09T02:23:00.000-07:002008-07-09T18:44:59.574-07:00auto-complete for vim<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9B-hesu9kJFDfwFXQlBQ8K8SvwawgqOn6CPvILrkSwncFR2eoikmEXfxO-SFS1Mih90TUTT437epiTjryqWeBH6uGh4cPa-MkzdUrKIj3wmK_kQtd1A8Cx-slv0S8Tks0ungLBqAuXvU/s1600-h/omnicppcomplete_on_vim.jpg"><img id="BLOGGER_PHOTO_ID_5220951895376999922" style="margin: 0px auto 10px; display: block; text-align: center;" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9B-hesu9kJFDfwFXQlBQ8K8SvwawgqOn6CPvILrkSwncFR2eoikmEXfxO-SFS1Mih90TUTT437epiTjryqWeBH6uGh4cPa-MkzdUrKIj3wmK_kQtd1A8Cx-slv0S8Tks0ungLBqAuXvU/s400/omnicppcomplete_on_vim.jpg" border="0" /></a><br /><div><br /><br /><div>auto-complete 是一般IDE 上面常有的功能<br />但是vim+ctags+omnicppcomplete就可以擁有auto-complete的開發環境<br />感覺上比visual studio上面提供的還要好用<br /><br /><br />omnicppcomplete can be downloaded <a href="http://vim.sourceforge.net/scripts/script.php?script_id=1520">here</a><br /><br /></div><br /><br /><blockquote>install details<br />1) Unzip the plugin to ~/.vim (unix) or %HOMEPATH%\vimfiles<br />(windows)<br />2) Run Vim and type the following command :<br /><br /><br /><blockquote>:helptags $HOME/.vim/doc or :helptags $HOME/vimfiles/doc </blockquote>3) Type :h omnicppcomplete and please read the installation<br />paragraph </blockquote><br /><br /><div><br />做完vim底下的設定之後可以製作自己的tags檔</div><br /><br /><div><blockquote>ctags -R --c++-kinds=+p --language-force=c++ --fields=+iaS --extra=+q<br />/usr/include<br /><span style="color: rgb(51, 204, 0);">註:tags file will be named as "tags" and located in your current position</span><br /></blockquote><br /><br />在使用omnicppcomplete之前需要在command mode底下載入剛剛製作的tag file<br /><br /><br /><blockquote>set tags=/usr/include/tags,./tags <br /><span style="color: rgb(51, 204, 0);">註:your tags file position might be different</span><br /></blockquote>最後,只要按^x^o就可以使用超強的auto-complete嚕!!</div><br /><br /><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvEB83kb7_gc0ckW8DQvJn1Ulj1vRDLl81whQmzO7S5cL3uisYgHbJEBSRIPkrC-vHWdBiPq6J44bsNb9e_92UQkMThdxyJsxEgsSPJwCHCJQzktC_1UEqREm5kxLsOMNoFG3XpJcOpCA/s1600-h/omnicppcomplete_on_vim.jpg"></a></div></div>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-44183122972416069822008-07-04T00:11:00.000-07:002008-07-09T05:21:15.591-07:00紅燒牛肉麵<p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">材料:<span lang="EN-US"><?xml:namespace prefix = o /><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">美國牛腱條<span lang="EN-US"> 2</span>條<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">番茄<span lang="EN-US">1</span>顆<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">薑<span lang="EN-US"> 3</span>片<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">蔥<span lang="EN-US"> 1</span>條<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">蒜<span lang="EN-US"> 2</span>瓣<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">料理米酒 <span lang="EN-US">1</span>杯<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">醬油 <span lang="EN-US">1</span>杯<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">豆瓣醬<span lang="EN-US"> 2</span>大匙<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">滷包<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;">水<span lang="EN-US">or </span>高湯<span lang="EN-US"> 500cc</span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><strong><span style="font-size:10;"><span style="color:#000000;">作法:<br /></span></span></strong><span style="color:#000000;"><span style="font-size:10;">1牛肉先汆燙過,切塊。番茄水煮後剝皮,切成四片<span lang="EN-US">; </span>蔥薑蒜切斷拍碎。<br /></span></span><span style="color:#000000;"><span style="font-size:10;">2取一燉鍋,加點油後爆炒蔥薑蒜,再把牛肉和豆瓣醬放入鍋中拌炒至<span lang="EN-US">6</span>分熟,再加入蕃茄、酒、醬油、滷包和高湯<span lang="EN-US">(</span>蓋過肉<span lang="EN-US">)</span>用大火煮滾後,再轉小火燉煮。<br /></span></span><span style="color:#000000;"><span lang="EN-US" style="font-size:10;">3.30</span><span style="font-size:10;">分鐘後,撈起滷包<span lang="EN-US">(</span>如喜歡中藥味重一點的可以不需要拿出<span lang="EN-US">)</span>,之後再續煮至湯汁濃縮成一半或牛肉變軟即可。<br /></span></span><span style="color:#000000;"><span style="font-size:10;">4可以依自己喜好,搭配麵條或是飯都可以。<span lang="EN-US"><o:p></o:p></span></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span lang="EN-US" style="font-size:10;"><o:p><span style="color:#000000;"></span></o:p></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="font-size:10;"><span style="color:#000000;"><strong>小叮嚀</strong></span></span></p><p style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: justify"><span style="color:#000000;"><span style="font-size:10;">-火候控制要小心,剛開始小火燜煮,用筷子攪動牛肉塊與番茄碎塊,否則易焦。<br /><br />reference:<br />http://blog.pixnet.net/janeliusy/post/4727388<br /></p></span></span>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-16026252079421918942008-06-14T12:08:00.000-07:002008-07-08T02:59:08.720-07:00installing boost and gtkmm under windows using dev-c++ as IDEdev-c++ and boost<br /><a href="http://wagjo.com/index.php?id=27">http://wagjo.com/index.php?id=27</a><br /><br />dev-c++ and gtkmm<br /><a href="http://pkme.bokee.com/4985325.html">http://pkme.bokee.com/4985325.html</a><br /><br />hope these aricals will help me finish my cross-platform projects...<br /><br />new gtkmm-devel package on windows can be found <a href="http://ftp.gnome.org/pub/gnome/binaries/win32/gtkmm/2.10/">here</a>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-91298541311490038472008-06-12T02:15:00.000-07:002008-06-12T20:22:33.808-07:00Boost regex tutorialc++的字串處理 已經較c方便很多<br />但是相較於perl之類的<br />還是望塵莫及<br /><br />但是boost提供了一個regex的工具<br />我在網路上面找到一個棒的<a href="http://www.onlamp.com/lpt/a/6535">教學</a><br /><br />簡單來說他是一個reguler expresstion的工具<br />他可以方便的提供你<br /><ol><li>在很長的字串中搜尋特定的資料格式內容</li><li>比對字串格式</li><li>同樣的字串做兩種不同格式之間的轉換</li><li>....</li></ol>你只要把格式的規則寫成一個Boost::Regex的物件<br />例如:<br /><br /><pre class="code" id="codemain">boost::regex re(<span class="literal">"<a\\s+href=\"([\\-:\\w\\d\\.\\/]+)\">"</span>);</pre>就可以用 boost::regex_match()或是boost::regex_search()來搜尋或是校對stringsamuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-36346948295941830272008-06-11T17:57:00.000-07:002008-06-12T20:20:35.382-07:00boost 1.305 增加網路以及影像處理的函式庫boost將asio包含再裡面嚕<br />以後寫c++再也不需要自己重到尾寫socket<br /><a href="http://www.boost.org/doc/libs/1_35_0/doc/html/boost_asio.html">這個網佔</a>有很豐富的資訊還有教學<br /><br />這次一併加入的還有一個<a href="http://stlab.adobe.com/gil/presentation/index.htm">gil</a>的影像工具<br />聽說功能也很強大<br />有空的時候希望有機會可以玩玩看<br /><br />以後跨平台programming真是越來越容易了samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-77008707440302348502008-06-11T06:07:00.000-07:002008-06-11T18:07:28.075-07:00好牧人有聲網我在網路上面無意間找到一個很棒的網站叫做<a href="http://sc.haomuren.org/DispCataMessages.asp?Category=05">『好牧人有聲網』</a><br />上面有很多很棒的有聲查經教材samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0tag:blogger.com,1999:blog-1770974693943942896.post-77269656858428780972008-06-11T05:53:00.000-07:002008-06-11T06:04:18.429-07:00鮮蝦蘆薈義大利燉飯risotto是義大利傳統的燉飯<br />上次吃過<span style="font-weight: bold;">台北-Mr. Rice 瑞司義大利燉飯</span>之後<br />覺得還蠻好吃的<br /><br />沒想到在youtube上面輕易的就找到一個教學影片<br /><br />其實risotto的煮法一點都不麻煩<br />不論是在宿舍還是在學校實驗室裡面<br />只要有平底鍋和電磁爐就可以輕易的完成了<br /><br />教學影片:<br /><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/i_ghPTaCdE0&hl=zh_TW"></param><embed src="http://www.youtube.com/v/i_ghPTaCdE0&hl=zh_TW" type="application/x-shockwave-flash" width="425" height="344"></embed></object>samuelhttp://www.blogger.com/profile/11422707099289832344noreply@blogger.com0