有時候有些字串需要compiler time時決定。通常前期先用menuconfig之類的工具設定好,再進行compile動作,此時新字串就會自動帶進.c中。
要做到這樣的效過,在gcc中可以用-D方式指定。
gcc編譯中加入 -DNEW_STRING=\"xxxxxxx\"。
在c原始碼內,利用一些字串連接的技巧串起來。或者可以自己加入#define中。
char a* = "I got "NEW_STRING"!!!!";
這樣目的就達成了。
有時候有些字串需要compiler time時決定。通常前期先用menuconfig之類的工具設定好,再進行compile動作,此時新字串就會自動帶進.c中。
要做到這樣的效過,在gcc中可以用-D方式指定。
gcc編譯中加入 -DNEW_STRING=\"xxxxxxx\"。
在c原始碼內,利用一些字串連接的技巧串起來。或者可以自己加入#define中。
char a* = "I got "NEW_STRING"!!!!";
這樣目的就達成了。
在ipv6情況下可以從/proc/net/ipv6_route印出當前default route資訊。試了一下發現內容順序以及值會跟隨目前routing作改變。在參考了route_linux.c以及how to get ipv6 default gateway from proc in linux之後,改寫出以下範例。
int getIpv6DefaultGatway(char *ifname, char *dgw, int dgw_size){
struct in6_addr src_addr;
int src_prefix;
struct in6_addr dst_addr;
int dst_prefix;
struct in6_addr gw_addr;
struct in6_addr any_addr;
unsigned int metrix;
unsigned int ref_cnt;
unsigned int usr_cnt;
unsigned int flag;
char devname[32];
FILE *fp;
int ret;
char dst[64];
char src[64];
char gw[64];
if(ifname == NULL){
return 0;
}
strcpy(dgw, "");
fp = fopen("/proc/net/ipv6_route", "r");
if(fp!=NULL){
memset(&any_addr, 0, sizeof(any_addr));
while((ret=fscanf(fp, "%s %x %s %x %s %x %x %x %x %s",
dst, &dst_prefix, src, &src_prefix, gw,
&metrix, &ref_cnt, &usr_cnt, &flag, devname)) != EOF){
/*return value must be parameter's number*/
if(ret != 10){
continue;
}
/*default route?*/
if(!strncmp(gw, "fe80", 4)
&& !strcmp(dst, "00000000000000000000000000000000") && dst_prefix == 0
&& !strcmp(ifname, devname)){
sprintf(gw, "%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c",
gw[0], gw[1], gw[2], gw[3], gw[4], gw[5], gw[6], gw[7], gw[8], gw[9],
gw[10], gw[11], gw[12], gw[13], gw[14], gw[15], gw[16], gw[17], gw[18], gw[19],
gw[20], gw[21], gw[22], gw[23], gw[24], gw[25], gw[26], gw[27], gw[28], gw[29],
gw[30], gw[31]);
inet_pton(PF_INET6, gw, &gw_addr);
inet_ntop(PF_INET6, &gw_addr, gw, sizeof(gw));
snprintf(dgw, dgw_size, "%s", gw);
//DO NOT BREAK to get last gateway
}
}
}
fclose(fp);
if(!strcmp(dgw, "")){
return 0;
}
return 1;
}
根據stackoverflow中Difference b/w exec( ) and system( ) in unix這篇文章中討論到的
exec: 覆蓋原本的程式,執行完即結束。
spawn: 啟動一個新的子程式(fork效用相當),並且和原本的程式同時進行。
system: 啟動一個新的子程式(fork效用相當),並且原本程式會等待該子程式執行完後才結束。
工作上覺得還蠻實用的程式片段。
struct task_struct *p;
struct siginfo info;
pid_t pid = -1;
for_each_process(p) {
if (!strcmp(p->comm, "process name")){
pid = p->pid;
break;
}
}
if(pid != -1){
if(p != NULL) {
info.si_signo = SIGUSR1;
info.si_code = SI_QUEUE;
info.si_int = 0x3;
send_sig_info(SIGUSR1, &info, p);
printk(KERN_EMERG "Send SIGUSR1 with value %d to %s(%d)\n", info.si_int, "process name", pid);
}
}
Kernel Korner - Why and How to Use Netlink Socket這篇寫得非常好,關於netlink的使用方法,範例也非常簡潔易懂。
這裡就貼上關於不使用group方式process送訊息至kernel。
User Space
#include <sys/socket.h>
#include <linux/netlink.h>
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
void main() {
sock_fd = socket(PF_NETLINK, SOCK_RAW,NETLINK_TEST);
memset(&src_addr, 0, sizeof(src_addr));
src__addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
src_addr.nl_groups = 0; /* not in mcast groups */
bind(sock_fd, (struct sockaddr*)&src_addr,
sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
nlh=(struct nlmsghdr *)malloc(
NLMSG_SPACE(MAX_PAYLOAD));
/* Fill the netlink message header */
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid(); /* self pid */
nlh->nlmsg_flags = 0;
/* Fill in the netlink message payload */
strcpy(NLMSG_DATA(nlh), "Hello you!");
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(fd, &msg, 0);
/* Read message from kernel */
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
recvmsg(fd, &msg, 0);
printf(" Received message payload: %s\n",
NLMSG_DATA(nlh));
/* Close Netlink Socket */
close(sock_fd);
}
Kernel Space
struct sock *nl_sk = NULL;
void nl_data_ready (struct sock *sk, int len)
{
wake_up_interruptible(sk->sleep);
}
void netlink_test() {
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh = NULL;
int err;
u32 pid;
nl_sk = netlink_kernel_create(NETLINK_TEST,
nl_data_ready);
/* wait for message coming down from user-space */
skb = skb_recv_datagram(nl_sk, 0, 0, &err);
nlh = (struct nlmsghdr *)skb->data;
printk("%s: received netlink message payload:%s\n",
__FUNCTION__, NLMSG_DATA(nlh));
pid = nlh->nlmsg_pid; /*pid of sending process */
NETLINK_CB(skb).groups = 0; /* not in mcast group */
NETLINK_CB(skb).pid = 0; /* from kernel */
NETLINK_CB(skb).dst_pid = pid;
NETLINK_CB(skb).dst_groups = 0; /* unicast */
netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
sock_release(nl_sk->socket);
}
#include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> int main() { unsigned char a[16]; char b[64] = ""; char c[64] = ""; inet_pton(PF_INET6, b, &a); inet_ntop(PF_INET6, b, c, sizeof(c)); fprintf(stderr, "c is %s\n", c); return 0; }
./ntop_test c is ::
2012.7.12更新
在這個範例中inet_pton轉換空字串其實是失敗的,並沒有寫入a中。
其實::的結果是c為空字串轉換回去的結果。
ipv4因為sin_addr中s_addr結構為uint32,可以利用"等於"直接作位址比較。
typedef uint32_t in_addr_t;
struct in_addr {
in_addr_t s_addr; /* IPv4 address */
};
比較方式可以像下面這樣。
(sa->sin_addr.s_addr != (((struct sockaddr_in *)&remote)->sin_addr.s_addr))
但是v6中sin6_addr就長得不太一樣了。
struct in6_addr {
union {
uint8_t u6_addr8[16];
uint16_t u6_addr16[8];
uint32_t u6_addr32[4];
} in6_u;
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
};
可以看到是使用陣列方式儲存。比較的話要使用memcmp方式來達成。
memcmp(sa_v6->sin6_addr.s6_addr, (((struct sockaddr_in6 *)&remote)->sin6_addr.s6_addr), 16) != 0
這個問題的來源可以參考Comparing a peer's IPv6 address with localhost。
這次是要在linux下將ipv4的程式改成ipv4/ipv6相容的程式。
原文可以看Porting applications to IPv6 HowTo。
首先利用sockaddr_storage取代傳統的sockaddr_in。當使用ipv4做溝通時,就將這個struct轉為sockaddr_in,使用ipv6溝通時,就要轉換為sockaddr_in6。sockaddr_storage裏面構造長得很像sockaddr_in和sockaddr_in6。
#if ULONG_MAX > 0xffffffff
# define __ss_aligntype __uint64_t
#else
# define __ss_aligntype __uint32_t
#endif
#define _SS_SIZE 128
#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))
struct sockaddr_storage
{
sa_family_t ss_family; /* Address family */
__ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
};
當我要使用的時候,我可以預先做轉好的動作備用。
struct sockaddr_storage sa;
struct sockaddr_in *sa_v4 = (struct sockaddr_in *)&sa;
struct sockaddr_in6 *sa_v6 = (struct sockaddr_in *)&sa;
或是你需要用的時候再做轉換。
(((struct sockaddr_in *)&sa)->sin_addr.s_addr) --->v4
(((struct sockaddr_in6 *)&sa)->sin6_addr.s6_addr) --->v6
接著,記得系統要build好ipv6的module,那樣的話,bind, recv這些通訊方法通通不用改。
而要分辨現在溝通模式是v4還是v6,可以看ss_family。
if(sa.ss_family == AF_INET){
...
}else if(sa.ss_family == AF_INET6){
...
}
最後就要有耐心的補完v6的邏輯。因為網路位址轉字串,位址比較都和v4不相同。詳細範例可以再看前面提到的Porting applications to IPv6 HowTo。
http://msdn.microsoft.com/zh-tw/magazine/gg622887(en-us).aspx
這篇說到javasscript運行的最佳化。
裡面說了一些觀念。不要為了很少執行到的程式作最佳化。在寫程式時就要想好比較省的想法。
舉了一些範例。
1. loop減少function call的重複性呼叫。
2. 最好一次把資料準備好再一次做function call處理,減少iteration。
3. jQuery loop最好把需要重複做"一樣"select的結果保存下來,避免重複做select動作。
http://msdn.microsoft.com/zh-tw/magazine/gg624360(en-us).aspx
javascript由於安全性限制,跨站抓取資料一般而言是不可行的。想要達到Cross domain的資料交換,這裡舉出了一些可行的作法。
1. 利用代理伺服器方式取得
2. 利用<script>方式,引入外部網址script,並將資料用json方式包覆
3. flash或silverlight第三方元件
4. 還不成熟的CORS(Cross-Origin Resource Sharing)標準
基本上作者是建議用2以滿足現階段的環境使用啦。
http://msdn.microsoft.com/zh-tw/magazine/hh243615(en-us).aspx
對於幹壞事而言一直有莫名的動力在。XSS出來很久了,我也一直努力想辦法在我們device裡面進行XSS攻擊。現在為止還沒有成功。現在卡在可動用字串長度太短。
防禦方式就從js與server端的檢查下手。
對於XSS更容易了解的範例,可以看XSS(Cross Site Scripting)攻擊會讓您遺失Cookie中的資料。
http://msdn.microsoft.com/en-us/magazine/ee819093.aspx
這篇文章很清楚的描述了如何去利用Firebug及一些plugin套件去對jQuery的script作debug,非常有用。
大綱項目如下
1. FireBug
2. FireQuery
3. FireFinder
4. JQuery Trace插件使用
5. 使用中斷點察看js
6. 查看event原始觸發者
7. 查看事件觸發堆疊 (console.group, console.groupEnd)
8. 計算程式區塊執行時間 (console.time, console.timeEnd)
9. 查看json與ajax溝通
10. 使用條件式中斷
另外也推薦jsbin作為javascript沙盒的快速產生預覽,這樣就不用辛苦的寫測試html了。
在石頭閒語的"在 C 程式中,使用 Regex (Regular Expression) library" http://blog.roodo.com/rocksaying/archives/3866523.html 看到,試著編譯一下,挺實用的。
特地引用原始碼,以後會用到。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>
int main() {
regex_t preg;
regmatch_t pmatch[10];
size_t nmatch = 10;
int cflags = REG_EXTENDED | REG_ICASE;
int i, len, rc;
char buf[1024], reg[256], str[256];
while(1) {
printf("Input exp: ");
fgets(reg, 256, stdin);
if(reg[0] == '\n') break;
strtok(reg,"\n");
printf("Input str: ");
fgets(str,256,stdin);
if(str[0] == '\n') break;
strtok(str,"\n");
if( regcomp(&preg, reg, cflags) != 0 ) {
puts("regex compile error!\n");
return 1;
}
rc = regexec(&preg, str, nmatch, pmatch, 0);
regfree(&preg);
if (rc != 0) {
printf("no match\n");
continue;
}
for (i = 0; i < nmatch && pmatch[i].rm_so >= 0; ++i) {
len = pmatch[i].rm_eo - pmatch[i].rm_so;
strncpy(buf, str + pmatch[i].rm_so, len);
buf[len] = '\0';
printf("sub pattern %d is %s\n", i, buf);
}
}
return 0;
}