Thursday, April 19, 2012

Blocking echo on terminal

There may be situation where in you may have to stop echo of characters on console while user types in. For ex: when prompted for password. This can be done very easily by using set of glibc library calls namely tcgetattr and tcsetattr. These library calls internally use ioctl on hardware to achieve the required functionality on terminal. You can achieve with following flow.

1)      Get old terminal configuration using tcgetattr
2)      Mask off echo
3)      Set new configuration to the terminal immediately using tcsetattr and TCSANOW.
4)      Do the work.
5)      Restore the old terminal settings.

Simple is it. So here is the code tested on linux box. Hope you will find it useful. Again I have tried to maintain at-most modularity so that these things can be used as APIs. Code should be portable easily across OSes using glibc.

#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <stdint.h>

#define TRUE  1
#define FALSE 0

int term_get_current (struct termios* term)
{
    if (term && !tcgetattr(STDIN_FILENO, term)) {
        return TRUE;
    }

    return FALSE;
}

int term_echo_set (struct termios* term, uint8_t echo_flag)
{
    if (term) {
        term->c_lflag = echo_flag? (term->c_lflag | ECHO):(term->c_lflag & ~ECHO);
        if (!tcsetattr(STDIN_FILENO, TCSANOW, term)) {
            return TRUE;
        }
    }

    return FALSE;
}

int term_restore (struct termios* term)
{
    if (term) {
        if(!tcsetattr(STDIN_FILENO, TCSANOW, term)) {
            return TRUE;
        }
    }

    return FALSE;
}

int main()
{
    struct termios term_old, term_new;
    char buf[50] = {0};

    if (!term_get_current(&term_old)) {
        printf("Unable to get terminal current instance\n");
        goto end;
    }

    term_new = term_old;

    printf("Password Please: ");

    if (!term_echo_set(&term_new, FALSE)) {
        printf("Unable to turn terminal echo off\n");
        goto end;
    }

    scanf("%s", buf);

    /*
     * If turning back echo ON does not succeed, do not exit!
     * Instead proceed to restore old terminal settings
     * In case of failure, do not try to echo the password
     */
    if (!term_echo_set(&term_new, TRUE)) {
        printf("Unable to turn terminal echo on\n");       
    } else {
        printf("\n\nYour password is: %s\n", buf);
    }

    if (!term_restore(&term_old)) {
        printf("Unable to restore old terminal settings\n");
    }

end: return 0;   
}


Compile using gcc. I have not shown output here since it needs to be tried on your own machines.

Off-Topic:

The man pages of tcsetattr has lot of other interesting options to play with terminal. Just have look at man pages.

Please leave comments or suggestions if you have.

Friday, March 30, 2012

Validating link local ipv6 address

I have seen in many places using string comparison to validate link local ipv6 address. However I feel this approach is not ideal and may not fit in all use cases.

For ex in c++ you may write:

string s = "fe80::1234";
s.find("fe80::");

something of this sort. However what if IP address in capitals? The above code will fail.

Ok lets take string library approach

strncasecmp(addr, "fe80:",5) == 0;

This may also work fine. However I feel we can do these things better and right way using standard libraries provided by glibc.

If you need to check for string, use inet_pton() and IN6_IS_ADDR_LINKLOCAL() combination to achieve validation. If you have sockaddr_in6 handy, you only need to use IN6_IS_ADDR_LINKLOCAL(). So here is the program I wrote. I feel modularity is maintained in program to some extent. There are two APIs. One takes string as argument while the other takes sockaddr as argument. In second case, sockaddr in casted to sockaddr_in6 and then validated for link-local ipv6 address.

#include <stdio.h>
#include <netinet/in.h>

typedef _Bool BOOL;

#define B_TRUE  1
#define B_FALSE 0

BOOL is_link_local_ip (const struct sockaddr* sock);
BOOL is_link_local_ip_str (const char* address);

static inline BOOL __is_link_local (struct sockaddr_in6* sock)
{
    return (((IN6_IS_ADDR_LINKLOCAL(&sock->sin6_addr)) == 1)
                    ? B_TRUE : B_FALSE);
}

BOOL is_link_local_ip (const struct sockaddr* sock)
{
    if (sock)
        if (sock->sa_family == AF_INET6) {
            struct sockaddr_in6 *temp =
                    (struct sockaddr_in6*)(sock);
            return __is_link_local (temp);
        }
           

    return B_FALSE;
}

BOOL is_link_local_ip_str (const char *address)
{
    struct sockaddr_in6 __in6_addr;

    if (address)
        if (inet_pton(AF_INET6, address, &(__in6_addr.sin6_addr)))
            return __is_link_local (&__in6_addr);

    return B_FALSE;
}

int main ()
{
    const char* ip_addr = "FE80::224:2CFF:FEA1:8a1";

    if (is_link_local_ip_str(ip_addr))
        printf("Address is ipv6 link_local\n");
    else
        printf("Address is not ipv6 link local\n");
}


So here is the output: Address is ipv6 link_local

You can test program with different test vectors. Apart from link-local, there are lot such macros that come in handy. Please refer: http://uw714doc.sco.com/en/man/html.3N/inet.3N.html

As always leave comment if you have better approach

Wednesday, March 21, 2012

Convert warnings to error with GCC

What happens if you execute below code?

int i = 10;
printf("%s Bad format specifier\n", i);


nandakumar@HERAMBA ~ $ gcc format.c
format.c: In function ‘main’:
format.c:6:2: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]


Output: Segmentation fault

This is common mistake programmer does. Here printf de-references address location 10 and print out the string value at that address. However 10 is not valid address in the address space and hence the program results in seg fault. GCC also warns about invalid format. However programmers tend to ignore the warnings too often and when errors do happen lot of time is spent to debug the error. The warnings are taken into consideration in above condition since program is too small. However, while working on larger projects, programmers tend to overlook on warnings.

There are two solutions though:

1) Program neatly
2) Find the error during compilation time itself

The first seems to be the ideal solution. However mistakes do happen. The second can be achieved using GCC options. GCC provides compiler switch '-Werror' to convert all warnings to errors. You can even have specific warnings to be shown as errors. For example, in above case we can only use '-Werror=format' to make format warning as error. This greatly helps you to reduce errors even.

How does modified output look like now?

nandakumar@HERAMBA ~ $ gcc -Werror format.c
format.c: In function ‘main’:
format.c:6:2: error: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Werror=format]
cc1: all warnings being treated as errors


Now we can see the change! There is an error in program which makes our life easy. That is it for now. Leave comments if you have extra suggestions.

Thursday, March 15, 2012

Thread Safety of 'errno' variable

Everyone knows that each time system call gets execured, the 'errno' will be set 'errno' value of last system call that failed. So it is a good practice to store 'errno' value for further processing if any system call getting called subsequently.

For ex:

socket(...); /* do not worry about args */
printf("Trying to open socket\n");
printf("The errno was = %d\n", errno);


So what is problem with above code? Well, printf is internally write system call. If printf fails, the 'errno' value will reflect the output of printf but not the socket error.

Now consider the example. I create two sockets. One with appletalk stream socket and other arbitrary protocol with datagram socket. We know stream socket is basically for TCP and SCTP based sockets. So the one with SOCK_STREAM gives error and the arbitrary also gives error. See the differences in 'errno'.

socket(AF_APPLETALK, SOCK_STREAM, 0);
socket(200, SOCK_DGRAM, 0);
printf("%d\n", errno);


Output: 97

I modify the code back.

socket(AF_APPLETALK, SOCK_STREAM, 0);
printf("%d\n", errno);
socket(200, SOCK_DGRAM, 0);


Output: 94

You will see difference in 'errno' which confirms our observation. So it is always good practice to store 'errno' you want to catch for particular system call before you proceed further.

Question comes about thread safety. 'errno' is global variable and resides in data segment which means not thread-safe. Does glibc puts any mutex locks around it. Oh thats really horrible thing and if you are using 'errno' directly, it does not make sense even. So how 'errno' is managed? What if 'errno' in one thread is modified by system call return of other thread?

Well glibc does this by making 'errno' per thread variable. For more information on gcc per thread variable see here: http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Thread-Local.html

So 'errno' modification is transparent to per thread and not across threads. Hence you can safely assume that 'errno' within a thread is localized and is completely abstracted from other threads. Consider the example:


#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define MAX_THREADS 3

pthread_barrier_t t_barrier;

void* syscall_thread1(void*);
void* syscall_thread2(void*);
void* syscall_thread3(void*);

int main()
{
    pthread_t tid[MAX_THREADS];

    /* It is not required to include main thread. Only for illustration */
    if (pthread_barrier_init(&t_barrier, NULL, MAX_THREADS+1)) {
        printf("Error in initializing pthread barrier\n");
        exit(1);
    }

    if (pthread_create(&tid[0], NULL, syscall_thread1, NULL)) {
        printf("Failed to create thread instance %d\n", 1);
    }
   
    if (pthread_create(&tid[1], NULL, syscall_thread2, NULL)) {
        printf("Failed to create thread instance %d\n", 2);
    }

    if (pthread_create(&tid[2], NULL, syscall_thread3, NULL)) {
        printf("Failed to create thread instance %d\n", 3);
    }

    /*
     * Make sure threads start simultaneously
     * atleast from code point of view,
     * may not be from scheduler point of view
     */
    pthread_barrier_wait(&t_barrier);

    /* Wait for each thread to complete */
    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);
    pthread_join(tid[2], NULL);

    pthread_barrier_destroy(&t_barrier);

    return 0;
}

void* syscall_thread1(void *instance)
{
    pthread_barrier_wait(&t_barrier);
    printf("In thread = %lu\n", pthread_self());
    if ((socket(AF_APPLETALK, SOCK_STREAM, 0)) == -1)
        perror("socket:");
}

void* syscall_thread2(void *instance)
{
    pthread_barrier_wait(&t_barrier);
    printf("In thread = %lu\n", pthread_self());
    if ((socket(200, SOCK_STREAM, 0)) == -1)
        perror("socket:");
}

void* syscall_thread3(void *instance)
{
    pthread_barrier_wait(&t_barrier);
    printf("In thread = %lu\n", pthread_self());
    if ((open("some_non_existing_file", O_RDWR)) == -1)
        perror("open:");
}


Output:

In thread = 3079547760
socket:: Socket type not supported
In thread = 3071155056
socket:: Address family not supported by protocol
In thread = 3062762352
open:: No such file or directory


Works as expected! However order of print depends on thread scheduling by linux scheduler. We may have to compile glibc with _REENTRANT option to achieve per thread 'errno' storage.


How about digging glibc code for a while?

/usr/include/errno.h says 'errno' is per-thread variable.

#ifdef  _ERRNO_H

/* Declare the `errno' variable, unless it's defined as a macro by
   bits/errno.h.  This is the case in GNU, where it is a per-thread
   variable.  This redeclaration using the macro still works, but it
   will be a function declaration without a prototype and may trigger
   a -Wstrict-prototypes warning.  */

#ifndef errno
extern int errno;
#endif


another snippet under /usr/include/i386-linux-gnu/bits/errno.h

#  if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value.  */
#   define errno (*__errno_location ())
#  endif
# endif /* !__ASSEMBLER__ */
#endif /* _ERRNO_H */


basically errno_location() function gets address of global 'errno' variable. As per the article in here: http://pauillac.inria.fr/~xleroy/linuxthreads/faq.html,

"Thus, for programs not linked with LinuxThreads, defining _REENTRANT makes no difference w.r.t. errno processing. But LinuxThreads redefines __errno_location() to return a location in the thread descriptor reserved for holding the current value of errno for the calling thread. Thus, each thread operates on a different errno location."

which means that each thread gets its own copy of 'errno'.

Small search in cscope for errno_location() leads to hurd/hurd/threadvar.h which says it all. What it means need to dig still further which even I am doing :-). The value seems to be obtained from some offset from thread stack pointer (just assuming).

/* Return the location of the value for the per-thread variable with index
   INDEX used by the thread whose stack pointer is SP.  */

extern unsigned long int *__hurd_threadvar_location_from_sp
  (enum __hurd_threadvar_index __index, void *__sp);
_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int *
__hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index,
                                   void *__sp)
{
  unsigned long int __stack = (unsigned long int) __sp;
  return &((__stack >= __hurd_sigthread_stack_base &&
            __stack < __hurd_sigthread_stack_end)
           ? __hurd_sigthread_variables
           : (unsigned long int *) ((__stack & __hurd_threadvar_stack_mask) +
                                    __hurd_threadvar_stack_offset))[__index];
}

/* Return the location of the current thread's value for the
   per-thread variable with index INDEX.  */

extern unsigned long int *
__hurd_threadvar_location (enum __hurd_threadvar_index __index) __THROW
     /* This declaration tells the compiler that the value is constant
        given the same argument.  We assume this won't be called twice from
        the same stack frame by different threads.  */
     __attribute__ ((__const__));

_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int *
__hurd_threadvar_location (enum __hurd_threadvar_index __index)
{
  return __hurd_threadvar_location_from_sp (__index,
                                            __thread_stack_pointer ());
}


Conclusion is glibc marks 'errno' as per thread variable and it is safe to access 'errno' across threads. Any comments or suggestions are greatly welcome

Thanks to wonderful book Linux System Programming by Robert Love through which I came to know that 'errno' is thread safe.

Monday, February 20, 2012

A few minutes of USB Outage


Yesterday one strange problem occurred in my laptop. I booted to vista for weekly backup. I have a Transcend external hard drive as well Seagate. The laptop has only 3 USB ports and I do not have a USB hub. The Transcend drive has two USB cables one for data and one for power. The other port was occupied by mouse. I had to plug out mouse for make room SeaGate hard drive.

As soon as I removed USB mouse, the windows started complaining about USB device malfunction. However SeaGate drive was detected while plugging both Transcend and mouse windows gave repeated errors. I rebooted and again problem was there. I did hard reboot nope again the problem persists. I booted to my xubuntu box, the same problem. ‘dmesg’ showed ‘Unable to enumerate USB device’. I got confused. The boot process took very long time. I was not able to check even bios due to CPU hog (by whom?).

I thought for a while. Hey wait a minute. If none of the OSes are unable to recognize then BIOS firmware ran into problem. I immediately went to download site of DELL and downloaded the BIOS firmware. The BIOS was flashed with the firmware I downloaded. After reboot I inserted the mouse and Transcend external hard drive. Hurrah!! It works. I am still confused why this sort of inconsistency happened with BIOS firmware. Is it the problem with inserting multiple external hard drives at a time? No, this is not possible. I am not hardware expert. Something went wrong with BIOS for sure

Saturday, February 18, 2012

A note on char* initialization

Again it is not something new :). Only thing is that I observed it recently. We can initialize a char* pointer with a constant string even after declaration. The restriction is of-course you cannot modify the content of pointer.

So what is the point. gcc puts the constant strings under read only section of data segment. Consider the example:

int main()
{
        char* str;
        str = "It is me";
        printf("%s\n", str);
}


If you think above code results in segmentation fault, nope. It works fine. So how does output look like

nandakumar@HERAMBA:~$ gcc test.c -o test
nandakumar@HERAMBA:~$ ./test
It is me

So how does gcc manage it. Here is snipped assembly output.

nandakumar@HERAMBA:~$ gcc -S test.c
nandakumar@HERAMBA:~$ head -5 test.s
    .file    "test.c"
    .section    .rodata
.LC0:
    .string    "It is me"
    .text

      
<snip>

You can even do this. It works great

int main()
{
        char* str;
        str = "It is me";
        printf("%s\n", str);
        str = "It is me again :-)";
        printf("%s\n", str);
}


Here is output:

nandakumar@HERAMBA:~$ gcc test.c -o test
nandakumar@HERAMBA:~$ ./test
It is me
It is me again :-)


So the data gets stored in read-only section of text segment and the pointer str points to the location in rodata. In second example you have two entries in rodata section.

nandakumar@HERAMBA:~$ gcc -S test.c
nandakumar@HERAMBA:~$ head -6 test.s
    .file    "test.c"
    .section    .rodata
.LC0:
    .string    "It is me"
.LC1:
    .string    "It is me again :-)"


Can I modify. Not at all. How can you modify rodata :-). It even does make sense the compiler puts it in read only section of text segment since we do not want to mess up with memory. Here is sample

int main()
{
        char* str;
        str = "It is me";
        printf("%s\n", str);
        str = "It is me again :-)";
        printf("%s\n", str);

        str[0] = 'P';
        printf("%s\n", str); /* Get LOST!! */
}


nandakumar@HERAMBA:~$ gcc test.c -o test
nandakumar@HERAMBA:~$ ./test
It is me
It is me again :-)
Segmentation fault


Note that having more constant strings bloats the executable size. Also be careful not to modify the contents. How can you make more precise about rodata? Consider this case

int main()
{
        char* str;
        str = "It is me";
        printf("str address is %p and content \"%s\"\n", str, str);
}


The output:

nandakumar@HERAMBA:~$ gcc test.c -o test
nandakumar@HERAMBA:~$ ./test
str address is 0x80484f0 and content "It is me"

The snipped version of objdump

nandakumar@HERAMBA:~$ objdump -D test

<snip>

Disassembly of section .rodata:

080484e8 <_fp_hw>:
 80484e8:    03 00                    add    (%eax),%eax
    ...

080484ec <_IO_stdin_used>:
 80484ec:    01 00                    add    %eax,(%eax)
 80484ee:    02 00                    add    (%eax),%al
 80484f0:    49                       dec    %ecx
 80484f1:    74 20                    je     8048513 <_IO_stdin_used+0x27>
 80484f3:    69 73 20 6d 65 00 25     imul   $0x2500656d,0x20(%ebx),%esi
 80484fa:    70 2d                    jo     8048529 <_IO_stdin_used+0x3d>
 80484fc:    25                       .byte 0x25
 80484fd:    73 0a                    jae    8048509 <_IO_stdin_used+0x1d>
    ... 


<snip>

The virtual memory location 0x80484f0 points to "It is me" (ignore the disassembled output). Note that the VM address may change every time you run.

That is it. I know you are feeling such silly thing but new for me. Leave your suggestions too!

Note:
1) Skipped C headers in code.
2) All codes were tested in Linux box and gcc compiler.
3) You can even run Valgrind to check sanity of code.

Small Correction: Earlier it was mentioned as read only data segment, however it is read only section of text segment. My apologies for mistake :-). Corrections are made at appropriate locations of write-up.

Saturday, January 28, 2012

My ISP finally happy with Ubuntu box


I was struggling to make my Ubuntu box work with login server of ISP. It was not getting better at all. Sometimes after 50 attempts, ISP used to say yes and login window appeared. However I was totally annoyed by this. When I switch back to Windows, everything was fine. I started digging to the problem myself rather than asking ISP itself (just for fun and learning).

1)      ISP provides a cable modem and recognizes the packets by MAC address of cable modem.
2)      I have a wireless router attached to my laptop.
3)      The WAN cable of modem is connected to wireless router.
4)      All my connections go via wireless router to cable modem to ISP Internet gateway.
5)      Wireless router has DHCP server to provide IP address to locally connected hosts.
6)      Of-course it acts like a NAT and router, in the sense you can have multiple hosts connecting to wireless router (not sure about limit).

The network setup is something like this:

NETWORK-SETUP
Let me come back to the problem of login server not responding. I struggled a lot. I thought the problem with wireless router and ISP may not be accepting the MAC other than my PC. No I was wrong, in windows everything was clean. Next, I pulled out wireless router and directly cabled modem to my PC. Again did not work out. I used to login from windows and work with Ubuntu for my net access. This was successful since login information was maintained in ISP side than locally in the system.

After so much of struggle, I decided to take packet captures of both windows and Ubuntu. I observed Ethernet packets and IP packets and they looked similar. Finally I gazed through TCP packets.

Aha here you are! Linux adds all TCP options to TCP packet while windows adds few. I knew this was problem but which options? I started disabling one by one

sudo sysctl net.ipv4.tcp_sack=0

This did not work

sudo sysctl net.ipv4.tcp_window_scaling=0

Na this did not work. I thought my assumption was wrong. I decided to give final try

sudo sysctl net.ipv4.tcp_timestamps=0

Hurrah!!! It worked out. I was really delighted. I updated the /etc/sysctl.conf and never faced the problem again.

So it is basically problem with tcp timestamp option which linux kernel includes by default. I really did not understand why this would give a problem. TCP timestamp just sends current clock of the system to avoid packets being recognized as duplicate during sequence number overflow. However they need not even synchronize with system clock. I raised this issue with ISP and let me see what happens further.

At the end of day, one more piece of learning and one more topic to write about ;). I just loved the investigations I carried out. It may be very silly problem to experts however for me it was seamless learning.

Here is the TCP packet capture of windows and linux. It shows Windows does not add TCP timestamp field in TCP packet during SYN state.



Courtesy: wireshark